1. 移动端使用 zepto 而不是 jquery

项目引入 zepto.js, zepto.touch.js。之后才可以用 tap 等 touch 事件

zepto.touch.js:

//     Zepto.js
//     (c) 2010-2016 Thomas Fuchs
//     Zepto.js may be freely distributed under the MIT license.

(function($) {
  var touch = {},
    touchTimeout,
    tapTimeout,
    swipeTimeout,
    longTapTimeout,
    longTapDelay = 750,
    gesture,
    down,
    up,
    move,
    eventMap,
    initialized = false;

  function swipeDirection(x1, x2, y1, y2) {
    return Math.abs(x1 - x2) >= Math.abs(y1 - y2)
      ? x1 - x2 > 0 ? 'Left' : 'Right'
      : y1 - y2 > 0 ? 'Up' : 'Down';
  }

  function longTap() {
    longTapTimeout = null;
    if (touch.last) {
      touch.el.trigger('longTap');
      touch = {};
    }
  }

  function cancelLongTap() {
    if (longTapTimeout) clearTimeout(longTapTimeout);
    longTapTimeout = null;
  }

  function cancelAll() {
    if (touchTimeout) clearTimeout(touchTimeout);
    if (tapTimeout) clearTimeout(tapTimeout);
    if (swipeTimeout) clearTimeout(swipeTimeout);
    if (longTapTimeout) clearTimeout(longTapTimeout);
    touchTimeout = tapTimeout = swipeTimeout = longTapTimeout = null;
    touch = {};
  }

  function isPrimaryTouch(event) {
    return (
      (event.pointerType == 'touch' || event.pointerType == event.MSPOINTER_TYPE_TOUCH) &&
      event.isPrimary
    );
  }

  function isPointerEventType(e, type) {
    return e.type == 'pointer' + type || e.type.toLowerCase() == 'mspointer' + type;
  }

  // helper function for tests, so they check for different APIs
  function unregisterTouchEvents() {
    if (!initialized) return;
    $(document)
      .off(eventMap.down, down)
      .off(eventMap.up, up)
      .off(eventMap.move, move)
      .off(eventMap.cancel, cancelAll);
    $(window).off('scroll', cancelAll);
    cancelAll();
    initialized = false;
  }

  function setup(__eventMap) {
    var now,
      delta,
      deltaX = 0,
      deltaY = 0,
      firstTouch,
      _isPointerType;

    unregisterTouchEvents();

    eventMap =
      __eventMap && 'down' in __eventMap
        ? __eventMap
        : 'ontouchstart' in document
          ? {
              down: 'touchstart',
              up: 'touchend',
              move: 'touchmove',
              cancel: 'touchcancel',
            }
          : 'onpointerdown' in document
            ? {
                down: 'pointerdown',
                up: 'pointerup',
                move: 'pointermove',
                cancel: 'pointercancel',
              }
            : 'onmspointerdown' in document
              ? {
                  down: 'MSPointerDown',
                  up: 'MSPointerUp',
                  move: 'MSPointerMove',
                  cancel: 'MSPointerCancel',
                }
              : false;

    // No API availables for touch events
    if (!eventMap) return;

    if ('MSGesture' in window) {
      gesture = new MSGesture();
      gesture.target = document.body;

      $(document).bind('MSGestureEnd', function(e) {
        var swipeDirectionFromVelocity =
          e.velocityX > 1
            ? 'Right'
            : e.velocityX < -1 ? 'Left' : e.velocityY > 1 ? 'Down' : e.velocityY < -1 ? 'Up' : null;
        if (swipeDirectionFromVelocity) {
          touch.el.trigger('swipe');
          touch.el.trigger('swipe' + swipeDirectionFromVelocity);
        }
      });
    }

    down = function(e) {
      if ((_isPointerType = isPointerEventType(e, 'down')) && !isPrimaryTouch(e)) return;
      firstTouch = _isPointerType ? e : e.touches[0];
      if (e.touches && e.touches.length === 1 && touch.x2) {
        // Clear out touch movement data if we have it sticking around
        // This can occur if touchcancel doesn't fire due to preventDefault, etc.
        touch.x2 = undefined;
        touch.y2 = undefined;
      }
      now = Date.now();
      delta = now - (touch.last || now);
      touch.el = $(
        'tagName' in firstTouch.target ? firstTouch.target : firstTouch.target.parentNode,
      );
      touchTimeout && clearTimeout(touchTimeout);
      touch.x1 = firstTouch.pageX;
      touch.y1 = firstTouch.pageY;
      if (delta > 0 && delta <= 250) touch.isDoubleTap = true;
      touch.last = now;
      longTapTimeout = setTimeout(longTap, longTapDelay);
      // adds the current touch contact for IE gesture recognition
      if (gesture && _isPointerType) gesture.addPointer(e.pointerId);
    };

    move = function(e) {
      if ((_isPointerType = isPointerEventType(e, 'move')) && !isPrimaryTouch(e)) return;
      firstTouch = _isPointerType ? e : e.touches[0];
      cancelLongTap();
      touch.x2 = firstTouch.pageX;
      touch.y2 = firstTouch.pageY;

      deltaX += Math.abs(touch.x1 - touch.x2);
      deltaY += Math.abs(touch.y1 - touch.y2);
    };

    up = function(e) {
      if ((_isPointerType = isPointerEventType(e, 'up')) && !isPrimaryTouch(e)) return;
      cancelLongTap();

      // swipe
      if (
        (touch.x2 && Math.abs(touch.x1 - touch.x2) > 30) ||
        (touch.y2 && Math.abs(touch.y1 - touch.y2) > 30)
      )
        swipeTimeout = setTimeout(function() {
          if (touch.el) {
            touch.el.trigger('swipe');
            touch.el.trigger('swipe' + swipeDirection(touch.x1, touch.x2, touch.y1, touch.y2));
          }
          touch = {};
        }, 0);
      else if ('last' in touch)
        if (deltaX < 30 && deltaY < 30) {
          // normal tap
          // don't fire tap when delta position changed by more than 30 pixels,
          // for instance when moving to a point and back to origin
          // delay by one tick so we can cancel the 'tap' event if 'scroll' fires
          // ('tap' fires before 'scroll')
          tapTimeout = setTimeout(function() {
            // trigger universal 'tap' with the option to cancelTouch()
            // (cancelTouch cancels processing of single vs double taps for faster 'tap' response)
            var event = $.Event('tap');
            event.cancelTouch = cancelAll;
            // [by paper] fix -> "TypeError: 'undefined' is not an object (evaluating 'touch.el.trigger'), when double tap
            if (touch.el) touch.el.trigger(event);

            // trigger double tap immediately
            if (touch.isDoubleTap) {
              if (touch.el) touch.el.trigger('doubleTap');
              touch = {};
            } else {
              // trigger single tap after 250ms of inactivity
              touchTimeout = setTimeout(function() {
                touchTimeout = null;
                if (touch.el) touch.el.trigger('singleTap');
                touch = {};
              }, 250);
            }
          }, 0);
        } else {
          touch = {};
        }
      deltaX = deltaY = 0;
    };

    $(document)
      .on(eventMap.up, up)
      .on(eventMap.down, down)
      .on(eventMap.move, move);

    // when the browser window loses focus,
    // for example when a modal dialog is shown,
    // cancel all ongoing events
    $(document).on(eventMap.cancel, cancelAll);

    // scrolling the window indicates intention of the user
    // to scroll, not tap or swipe, so cancel all ongoing events
    $(window).on('scroll', cancelAll);

    initialized = true;
  }

  [
    'swipe',
    'swipeLeft',
    'swipeRight',
    'swipeUp',
    'swipeDown',
    'doubleTap',
    'tap',
    'singleTap',
    'longTap',
  ].forEach(function(eventName) {
    $.fn[eventName] = function(callback) {
      return this.on(eventName, callback);
    };
  });

  $.touch = { setup: setup };

  $(document).ready(setup);
})(Zepto);
Copyright © Guanghui Wang all right reserved,powered by GitbookFile Modified: 2019-08-25 13:56:34

results matching ""

    No results matching ""