Browse Source

优化 carousel 移动端滑动切换

pull/1446/head
sight 12 months ago
parent
commit
462ed13f18
  1. 18
      src/modules/carousel.js
  2. 104
      src/modules/lay.js

18
src/modules/carousel.js

@ -331,13 +331,27 @@ layui.define(['jquery', 'lay'], function(exports){
if(options.elem.data('haveEvents')) return;
// 移入移出容器
options.elem.on('mouseenter', function(){
options.elem.on('mouseenter touchstart', function(){
if (that.config.autoplay === 'always') return;
clearInterval(that.timer);
}).on('mouseleave', function(){
}).on('mouseleave touchend', function(){
if (that.config.autoplay === 'always') return;
that.autoplay();
});
var touchEl = options.elem;
var isVertical = options.anim === 'updown';
lay.touchSwipe(touchEl, {
onTouchEnd: function(e, state){
var duration = Date.now() - state.timeStart;
var delta = isVertical ? state.deltaY : state.deltaX;
var speed = delta / duration;
var shouldSwipe = Math.abs(speed) > 0.25 || Math.abs(delta) > touchEl[isVertical ? 'height' : 'width']() / 3;
if(shouldSwipe){
that.slide(delta > 0 ? '' : 'sub');
}
}
})
options.elem.data('haveEvents', true);
};

104
src/modules/lay.js

@ -505,6 +505,110 @@
}
};
/**
* 检测是否支持 Passive Event Listeners
* 引用自 https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
* @type {boolean}
*/
lay.passiveSupported = function(){
var passiveSupported = false;
try {
var opts = Object.defineProperty({}, 'passive', {
get: function() {
passiveSupported = true;
}
});
window.addEventListener('test', null, opts);
window.removeEventListener('test', null, opts);
} catch (err) {}
return passiveSupported;
}();
/**
* 是否支持 touch 事件
*/
lay.touchEventsSupported = function(){
return 'ontouchstart' in window;
};
/**
* @typedef touchSwipeState
* @prop {{x: number,y: number}} coordsStart - 初始坐标
* @prop {{x: number,y: number}} coordsEnd - 结束坐标
* @prop {number} deltaX - X 轴变化量
* @prop {number} deltaY - Y 轴变化量
* @prop {'none'|'right'|'left'|'up'|'down'} direction - 滑动方向
* @prop {Date} timeStart 开始时间
*/
/**
* @callback touchSwipeCallback
* @param {TouchEvent} e 滑动事件
* @param {touchSwipeState} state 滑动相关的状态
*/
/**
* 基于 touch 事件的触摸滑动
* @param {string | HTMLElement | JQuery} elem - HTML 元素
* @param {{onTouchStart?: touchSwipeCallback, onTouchMove?: touchSwipeCallback, onTouchEnd?: touchSwipeCallback}} opts - 配置项
*/
lay.touchSwipe = function(elem, opts){
var options = opts
var targetElem = lay(elem)[0];
if(!targetElem || !lay.touchEventsSupported()) return;
var state = {
coordsStart: {x:0, y:0},
coordsEnd: {x:0, y:0},
deltaX: 0,
deltaY: 0,
direction:'none', // 'up','down','left','right','none
timeStart: null
}
var onStart = function(e){
if(e.touches.length !== 1) return;
bindEvents();
state.timeStart = Date.now();
state.coordsStart.x = state.coordsEnd.x = e.touches[0].clientX;
state.coordsStart.y = state.coordsEnd.y = e.touches[0].clientY;
options.onTouchStart && options.onTouchStart(e, state);
}
var onMove = function(e){
e.preventDefault();
state.coordsEnd.x = e.touches[0].clientX;
state.coordsEnd.y = e.touches[0].clientY;
state.deltaX = state.coordsStart.x - state.coordsEnd.x;
state.deltaY = state.coordsStart.y - state.coordsEnd.y;
if(Math.abs(state.deltaX) > Math.abs(state.deltaY)){
state.direction = state.deltaX > 0 ? 'left' : 'right';
}else{
state.direction = state.deltaY > 0 ? 'up' : 'down';
}
options.onTouchMove && options.onTouchMove(e, state);
}
var onEnd = function(e){
options.onTouchEnd && options.onTouchEnd(e, state);
unbindEvents();
}
var bindEvents = function(){
targetElem.addEventListener('touchmove', onMove, lay.passiveSupported ? { passive: false} : false);
targetElem.addEventListener('touchend', onEnd);
targetElem.addEventListener('touchcancel', onEnd);
}
var unbindEvents = function(){
targetElem.removeEventListener('touchmove', onMove);
targetElem.removeEventListener('touchend', onEnd, lay.passiveSupported ? { passive: false} : false);
targetElem.removeEventListener('touchcancel', onEnd);
}
targetElem.addEventListener('touchstart', onStart);
}
/*
* lay 元素操作

Loading…
Cancel
Save