在开发移动端项目经常会遇到电脑调试效果没问题,切换到移动端设备出现异常,比如在GIS或者轮播图(含有拖拽行为)等组件时,电脑开发可以正常执行拖拽事件,但到了移动设备会出现事件不被触发的情况,这里可以使用"elm-pep.js"这个库来实现全局事件映射,这里把贴出相关代码,供自己学习记录:
<script>
// 兼容ios触摸
var primaryTouchId = null;
// 当前触摸事件target
var mouseCaptureTarget = null;
if (!("PointerEvent" in window)) {
// 初始化
definePointerCapture();
// 只对没有触摸事件的设备执行polyfill
if (!("TouchEvent" in window)) {
addMouseToPointerListener(document, "mousedown", "pointerdown");
addMouseToPointerListener(document, "mousemove", "pointermove");
addMouseToPointerListener(document, "mouseup", "pointerup");
}
// 事件注册
addTouchToPointerListener(document, "touchstart", "pointerdown");
addTouchToPointerListener(document, "touchmove", "pointermove");
addTouchToPointerListener(document, "touchend", "pointerup");
}
// 注册事件到组件原型上
function definePointerCapture() {
Element.prototype.setPointerCapture = Element.prototype.setCapture;
Element.prototype.releasePointerCapture =
Element.prototype.releaseCapture;
}
// 添加监听器
function addMouseToPointerListener(target, mouseType, pointerType) {
target.addEventListener(mouseType, function (mouseEvent) {
var pointerEvent = new MouseEvent(pointerType, mouseEvent);
pointerEvent.pointerId = 1;
pointerEvent.isPrimary = true;
pointerEvent.pointerType = "mouse";
pointerEvent.width = 1;
pointerEvent.height = 1;
pointerEvent.tiltX = 0;
pointerEvent.tiltY = 0;
// 点击按钮按住的时候pressure值为0.5,用作事件识别
"buttons" in mouseEvent && mouseEvent.buttons !== 0
? (pointerEvent.pressure = 0.5)
: (pointerEvent.pressure = 0);
// if already capturing mouse event, transfer target
// and don't forget implicit release on mouseup.
// 若已捕获鼠标事件,则获取到事件对象,当松开鼠标事件释放对象
var target = mouseEvent.target;
if (mouseCaptureTarget !== null) {
target = mouseCaptureTarget;
if (mouseType === "mouseup") {
mouseCaptureTarget = null;
}
}
target.dispatchEvent(pointerEvent);
if (pointerEvent.defaultPrevented) {
mouseEvent.preventDefault();
}
});
}
// 核心代码:事件映射
function addTouchToPointerListener(target, touchType, pointerType) {
target.addEventListener(touchType, function (touchEvent) {
var changedTouches = touchEvent.changedTouches;
var nbTouches = changedTouches.length;
for (var t = 0; t < nbTouches; t++) {
var pointerEvent = new CustomEvent(pointerType, {
bubbles: true,
cancelable: true,
});
pointerEvent.ctrlKey = touchEvent.ctrlKey;
pointerEvent.shiftKey = touchEvent.shiftKey;
pointerEvent.altKey = touchEvent.altKey;
pointerEvent.metaKey = touchEvent.metaKey;
var touch = changedTouches.item(t);
pointerEvent.clientX = touch.clientX;
pointerEvent.clientY = touch.clientY;
pointerEvent.screenX = touch.screenX;
pointerEvent.screenY = touch.screenY;
pointerEvent.pageX = touch.pageX;
pointerEvent.pageY = touch.pageY;
var rect = touch.target.getBoundingClientRect();
pointerEvent.offsetX = touch.clientX - rect.left;
pointerEvent.offsetY = touch.clientY - rect.top;
pointerEvent.pointerId = 1 + touch.identifier;
// 设置默认鼠标事件值
pointerEvent.button = 0;
pointerEvent.buttons = 1;
pointerEvent.movementX = 0;
pointerEvent.movementY = 0;
pointerEvent.region = null;
pointerEvent.relatedTarget = null;
pointerEvent.x = pointerEvent.clientX;
pointerEvent.y = pointerEvent.clientY;
// 鼠标事件
pointerEvent.pointerType = "touch";
pointerEvent.width = 1;
pointerEvent.height = 1;
pointerEvent.tiltX = 0;
pointerEvent.tiltY = 0;
pointerEvent.pressure = 1;
// 第一个触摸点设置为目标事件
if (touchType === "touchstart" && primaryTouchId === null) {
primaryTouchId = touch.identifier;
}
pointerEvent.isPrimary =
touch.identifier === primaryTouchId;
// 抬起触摸点,释放触摸事件对象
if (touchType === "touchend" && pointerEvent.isPrimary) {
primaryTouchId = null;
}
touchEvent.target.dispatchEvent(pointerEvent);
if (pointerEvent.defaultPrevented) {
touchEvent.preventDefault();
}
}
});
}
</script>