crossvent:封装跨平台事件绑定的库
跨平台的触摸事件
利用crossvent
封装绑定跨平台拖拽事件的方法touchy
,以便支持移动端和pc端
根据环境获取的触摸事件名,用懒加载的方式替换掉touchy函数,之后绑定事件不需要再判断
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| import { add as addEvent } from 'crossvent';
let touchy = function (el, type, fn) { const touch = { mouseup: 'touchend', mousedown: 'touchstart', mousemove: 'touchmove' }; const pointers = { mouseup: 'pointerup', mousedown: 'pointerdown', mousemove: 'pointermove' }; const microsoft = { mouseup: 'MSPointerUp', mousedown: 'MSPointerDown', mousemove: 'MSPointerMove' }; if (window.navigator.pointerEnabled) { touchy = function (el, type, fn) { addEvent(el, pointers[type], fn); }; } else if (window.navigator.msPointerEnabled) { touchy = function (el, type, fn) { addEvent(el, microsoft[type], fn); }; } else { touchy = function (el, type, fn) { addEvent(el, touch[type], fn); addEvent(el, type, fn); }; }
touchy(el, type, fn); };
|
初始化事件
1 2 3 4 5 6 7 8 9 10 11 12 13
| const documentElement = document.documentElement;
function draggable (dom) { initEvents();
function initEvents () { touchy(dom, 'mousedown', mousedown); touchy(documentElement, 'mousemove', mousemove); touchy(documentElement, 'mouseup', mouseup); }
}
|
这里在documentElement
上绑定mousemove
和mouseup
事件,是因为避免渲染速度低于拖拽速度,导致鼠标超出拖拽范围而无法拖拽和释放
这里提一下绑定事件时有一个passive
选项,具体可以查看 使用 passive 改善的滚屏性能,可以设置为false
,使事件回调可以使用e.preventDefault
禁用默认的行为
mousedown
1 2 3 4 5 6
| function mousedown (e) { active = true; e = getEventHost(e); _moveX = e.clientX; _moveY = e.clientY; }
|
在documentElement
上绑定mousemove
和mouseup
事件,所以需要标记是否是处于拖拽状态,然后mousemove
和mouseup
中判断如果不是拖拽状态则跳出函数。
为了适配移动端(touchEvent
没有clientX
、clientY
、x
、y
),引出了getEventHost
1 2 3 4 5 6 7 8 9
| function getEventHost (e) { if (e.targetTouches && e.targetTouches.length) { return e.targetTouches[0]; } if (e.changedTouches && e.changedTouches.length) { return e.changedTouches[0]; } return e; }
|
我们看看touch、targetTouches、changedTouches的定义
- touches: 当前屏幕上所有触摸点的列表
- targetTouches: 当前对象上所有触摸点的列表
- changedTouches: 涉及当前(引发)事件的触摸点的列表
mousemove
这里实现的是可拖拽范围为document
的可视区域
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| function mousemove (e) { if (!active) { return; } e = getEventHost(e); const { x, y, height, width } = dom.getBoundingClientRect(); const curLeft = x + e.clientX - _moveX; const curTop = y + e.clientY - _moveY;
dom.style.left = `${clamp(curLeft, 0, documentElement.clientWidth - width - 1)}px`; dom.style.top = `${clamp(curTop, 0, documentElement.clientHeight - height)}px`; _moveX = e.clientX; _moveY = e.clientY; }
function clamp (value, min, max) { return Math.min(Math.max(value, min), max); }
|
mouseup
1 2 3
| function mouseup () { active = false; }
|
总结
我们可以自定义mousemove的行为,但整体的框架不会变