移动端事件有哪些
- Touch触摸事件
- Pointer指针事件
移动端事件的发展
- 没有移动端事件,大部分鼠标事件在移动端一样有用
- 苹果推出Touch触摸事件
- 微软推出Pointer指针事件(统一鼠标、触摸、笔)
兼容性(can i use)
- 移动和pc都适配推荐使用Pointer指针事件
Touch触摸事件
Touch事件基础
Touch事件的类型
注意事项
Touch事件的特征检测
1.Touch 事件的类型
- touchstart 元素上触摸开始时触发
- touchmove 元素上触摸移动时触发
- touchend 手指从元素上离开时触发
- touchcancel 触摸被打断时触发
const $box = document.getElementById('box');
$box.addEventListener('touchstart', startHandler, false);
$box.addEventListener('touchmove', moveHandler, false);
$box.addEventListener('touchend', endHandler, false);
$box.addEventListener('touchcancel', cancelHandler, false); //右键弹出菜单,电话和弹窗进入
function startHandler() {
console.log('touchstart');
}
function moveHandler() {
console.log('touchmove');
}
function endHandler() {
console.log('touchend');
}
function cancelHandler() {
console.log('touchcancel');
}
2.注意事项
- Touch 事件在 PC 端不会触发,鼠标事件在 PC 端和移动端都会触发
- 即使触摸点移出目标元素,touchmove 事件依然会持续触发,mousemove 事件不会再触发
- 触发 touchmove 与 touchend 事件,一定要先触发 touchstart
$box.addEventListener('mouseover', mouseHandler, false);
$box.addEventListener('mouseenter', mouseHandler, false);
$box.addEventListener('mousedown', mouseHandler, false);
$box.addEventListener('mousemove', mouseHandler, false); //移动端会阻止 只能点击触发
$box.addEventListener('mouseup', mouseHandler, false);
$box.addEventListener('mouseout', mouseHandler, false);
$box.addEventListener('mouseleave', mouseHandler, false);
$box.addEventListener('click', mouseHandler, false);
function mouseHandler(evt) {
console.log(evt.type);
}
3.Touch 事件的特征检测(判断浏览器支不支持 Touch 事件)
//console.log('onload' in window);
console.log('ontouchstart' in window);
if ('ontouchstart' in window) {
console.log('支持');
}
Touch事件的event对象
event对象的常用属性
触摸点的常用属性
阻止浏览器的默认行为
1.event 对象的常用属性
- type 事件类型
- target 目标元素
- touches 屏幕上的所有触摸点
- targetTouches 起始于目标上的所有触摸点
- changedTouches 事件触发时,状态发生了改变的所有触摸点
$box.addEventListener('touchstart', startHandler, false);
function startHandler(evt) {
console.log('touchstart');
console.log(evt);
console.log(evt.type);
console.log(evt.target);
console.log(evt.touches);
console.log(evt.targetTouches);
console.log(evt.changedTouches);
}
2.触摸点的常用属性
- identifier 触摸点id(唯一标识符),一般多指触摸有用
- target 目标元素
- screenX/screenY 触点相对于屏幕左边缘的X、Y坐标
- clientX/clientY 触摸点相对于可视区左边缘的X,Y坐标 (不计算滚动条)
- pageX/pageY 触摸点相对于页面左边缘的X,Y坐标 (计算滚动条)
$box.addEventListener('touchstart', startHandler, false);
$box.addEventListener('touchend', endHandler, false);
$box.addEventListener('touchcancel', cancelHandler, false);
function startHandler(evt) {
const touch = evt.changedTouches[0];
console.log(touch);
console.log(touch.identifier);
console.log(touch.target);
console.log(touch.screenX, touch.screenY);
console.log(touch.clientX, touch.clientY);
console.log(touch.pageX, touch.pageY);
}
function endHandler(evt) {
console.log('touchend');
console.log(evt.touches.length);
console.log(evt.targetTouches.length);
console.log(evt.changedTouches.length);
}
function cancelHandler(evt) {
console.log('touchcancel');
console.log(evt.touches.length);
console.log(evt.targetTouches.length);
console.log(evt.changedTouches.length);
}
3.阻止浏览器的默认行为
- 阻止 scrolling, pinch/zoom, 鼠标事件等默认行为
<style>
.box {
width: 200px;
height: 200px;
background-color: red;
/* 处理所有触摸操作 */
/* touch-action: auto; */
/* 禁止平移和缩放 */
/* touch-action: none; */
/* 平移 */
/* touch-action: pan-x; */
/* touch-action: pan-y; */
/* 只允许进行滚动和持续缩放操作,不允许双击缩放 */
/* touch-action: manipulation; */
}
</style>
function startHandler(evt) {
evt.preventDefault();
}
$box.addEventListener('mouseover', mouseHandler, false);
$box.addEventListener('mouseenter', mouseHandler, false);
$box.addEventListener('mousedown', mouseHandler, false);
$box.addEventListener('mousemove', mouseHandler, false);
$box.addEventListener('mouseup', mouseHandler, false);
$box.addEventListener('mouseout', mouseHandler, false);
$box.addEventListener('mouseleave', mouseHandler, false);
$box.addEventListener('click', mouseHandler, false);
function mouseHandler(evt) {
console.log(evt.type);
}
单指拖拽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>单指拖拽</title>
<style>
.box {
width: 200px;
height: 200px;
background-color: red;
}
</style>
</head>
<body style="height: 2000px">
<div id="box" class="box"></div>
<script>
const drag = $el => {
// 每次拖拽最开始的触摸点
const startPoint = {};
// 拖拽过程中移动到的点
const movePoint = {};
// 被拖拽元素的当前位置
const curPos = {
x: 0,
y: 0
};
$el.addEventListener('touchstart', startHandler, false);
$el.addEventListener('touchmove', moveHandler, false);
$el.addEventListener('touchend', endHandler, false);
$el.addEventListener('touchcancel', endHandler, false);
function startHandler(evt) {
//阻止拖拽产生的滚动条
evt.preventDefault();
const touch = evt.changedTouches[0];
startPoint.x = touch.pageX;
startPoint.y = touch.pageY;
// console.log(startPoint);
}
function moveHandler(evt) {
const touch = evt.changedTouches[0];
movePoint.x = curPos.x + touch.pageX - startPoint.x;
movePoint.y = curPos.y + touch.pageY - startPoint.y;
$el.style.transform = `translate3d(${movePoint.x}px,${movePoint.y}px,0)`;
}
function endHandler() {
curPos.x = movePoint.x;
curPos.y = movePoint.y;
}
};
drag(document.getElementById('box'));
</script>
</body>
</html>
应用场景
-
touchstart 事件可用于元素触摸的交互,比如页面跳转,标签页切换
-
touchmove 事件可用于页面的滑动特效,网页游戏,画板
-
touchend 事件主要跟 touchmove 事件结合使用
-
touchcancel 使用率不高
Pointer指针事件
Pointer事件基础
1.Pointer 事件的类型
pointerover/pointerenter/pointerout/pointerleave/pointerdown/pointermove/pointerup/pointercancel
// pointer
$box.addEventListener('pointerover', pointerHandler, false);
$box.addEventListener('pointerenter', pointerHandler, false);
$box.addEventListener('pointerdown', pointerHandler, false);
$box.addEventListener('pointermove', pointerHandler, false);
$box.addEventListener('pointerup', pointerHandler, false);
$box.addEventListener('pointerout', pointerHandler, false);
$box.addEventListener('pointerleave', pointerHandler, false);
2.注意事项
- Pointer 事件直接继承了鼠标事件,在此基础上又添加了其他一些内容,处理 Pointer 事件和处理鼠标事件几乎一致
- Pointer 事件在 PC 端和移动端都会触发
- 触摸点移出目标元素,touchmove 事件依然会持续触发,pointermove 和 mousemove 事件不会再触发
3.Pointer 事件的特征检测(判断浏览器支不支持 Pointer 事件)
if ('onpointerdown' in window) {
console.log('支持 Pointer 事件');
}
Pointer事件的event对象
event对象的常用属性 阻止浏览器的默认行为
1.event对象的常用属性
-
pointerId 指针id(唯一标识符)
-
type 事件类型
-
pointerType 指针类型(鼠标/笔/触摸等)
-
target 目标元素
-
screenX/screenY 指针相对于屏幕左边缘的X、Y坐标
-
clientX/clientY 指针相对于可视区域左边缘的X、Y坐标。不包括任何滚动偏移
-
x/y clientX/clientY 的别名
-
pageX/pageY 指针相对于 HTML 文档左边缘的X、Y坐标。包括滚动偏移
$box.addEventListener('pointerover', pointerHandler, false);
$box.addEventListener('pointerenter', pointerHandler, false);
$box.addEventListener('pointerdown', pointerHandler, false);
$box.addEventListener('pointermove', pointerHandler, false);
$box.addEventListener('pointerup', pointerHandler, false);
$box.addEventListener('pointerout', pointerHandler, false);
$box.addEventListener('pointerleave', pointerHandler, false);
$box.addEventListener('pointercancel', pointerHandler, false);
function pointerHandler(evt) {
console.log(evt);
console.log(evt.pointerId);
console.log(evt.type);
console.log(evt.pointerType);
console.log(evt.target);
console.log(evt.screenX, evt.screenY);
console.log(evt.clientX, evt.clientY);
console.log(evt.x, evt.y);
console.log(evt.pageX, evt.pageY);
}
2.阻止浏览器的默认行为
- 阻止 scrolling, pinch/zoom, 鼠标事件等默认行为
- Pointer 的事件处理函数中,evt.preventDefault() 阻止的是 PC 端的默认行为(不能阻止 scrolling, pinch/zoom, 鼠标事件等默认行为,可以阻止图片拖动的默认行为)
- 可以在 touch 的事件处理函数中使用 evt.preventDefault() 阻止移动端的默认行为
- touch-action 设置触摸操作时浏览器的默认行为(touch-action: none;阻止所有默认)
$box.addEventListener('pointerover', pointerHandler, false);
$box.addEventListener('pointerenter', pointerHandler, false);
$box.addEventListener('pointerdown', pointerHandler, false);
$box.addEventListener('pointermove', pointerHandler, false);
$box.addEventListener('pointerup', pointerHandler, false);
$box.addEventListener('pointerout', pointerHandler, false);
$box.addEventListener('pointerleave', pointerHandler, false);
$box.addEventListener('pointercancel', pointerHandler, false);
function pointerHandler(evt) {
evt.preventDefault();
}
$box.addEventListener('touchstart', startHandler, false);
function startHandler(evt) {
阻止移动端默认行为
evt.preventDefault();
}
单指拖拽
const drag = $el => {
// 每次拖拽最开始的触摸点
const startPoint = {};
// 拖拽过程中移动到的点
const movePoint = {};
// 被拖拽元素的当前位置
const curPos = {
x: 0,
y: 0
};
$el.addEventListener('pointerdown', startHandler, false);
// $el.addEventListener('pointermove', moveHandler, false);
// $el.addEventListener('pointerup', endHandler, false);
// $el.addEventListener('pointercancel', endHandler, false);
$el.addEventListener(
'touchstart',
evt => {
evt.preventDefault();
},
false
);
function startHandler(evt) {
startPoint.x = evt.pageX;
startPoint.y = evt.pageY;
document.addEventListener('pointermove', moveHandler, false);
document.addEventListener('pointerup', endHandler, false);
document.addEventListener('pointercancel', endHandler, false);
}
function moveHandler(evt) {
evt.preventDefault();
movePoint.x = curPos.x + evt.pageX - startPoint.x;
movePoint.y = curPos.y + evt.pageY - startPoint.y;
$el.style.transform = `translate3d(${movePoint.x}px, ${movePoint.y}px, 0)`;
}
function endHandler() {
curPos.x = movePoint.x;
curPos.y = movePoint.y;
document.removeEventListener('pointermove', moveHandler, false);
document.removeEventListener('pointerup', endHandler, false);
document.removeEventListener('pointercancel', endHandler, false);
}
};
drag(document.getElementById('box'));
IOS手势事件
该事件只有IOS上的浏览器支持!
- gesturestart : 手指触碰当前元素,屏幕上有两个或者两个以上的手指
- gesturechange : 手指触碰当前元素,屏幕上有两个或者两个以上的手指位置在发生移动
- gestureend : 在gesturestart后, 屏幕上只剩下两根以下(不包括两根)的手指
手势事件 touchEvent 的属性
- 属性 rotation : 表示手指变化引起的旋转角度,负值表示逆时针旋转,正值表示顺时针旋转。
- 属性 scale : 表示两个手指间距离的变化情况(例如向内收缩会缩短距离);这个值从 1 开始,并随距离拉大而 增长,随距离缩短而减小。根据我们的生理极限,不允许出现负值
手势模拟
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>手势模拟</title>
<style>
img {
width: 100%;
}
.box {
width: 200px;
height: 200px;
background-color: red;
}
</style>
</head>
<body>
<img id="gesture" src="./gesture.png" alt="移动端手势" />
<!-- <div id="box" class="box"></div> -->
<script>
// 1.滑(扫)动手势
function swipe($el, cb) {
// 最开始的触摸点
const start = {};
// 时间和距离阈值
const threshold = {
time: 500,
distance: 100
};
$el.addEventListener('pointerdown', startHandler, false);
// 阻止移动端默认行为
$el.addEventListener(
'touchstart',
evt => {
evt.preventDefault();
},
false
);
function startHandler(evt) {
// 阻止 PC 端默认行为
evt.preventDefault();
start.time = new Date().getTime();
start.x = evt.pageX;
start.y = evt.pageY;
document.addEventListener('pointerup', endHandler, false);
document.addEventListener('pointercancel', endHandler, false);
}
function endHandler(evt) {
const delta = {};
let direction = '';
delta.time = new Date().getTime() - start.time;
delta.x = evt.pageX - start.x;
delta.y = evt.pageY - start.y;
// 判断是否是扫动手势
if (
delta.time > threshold.time ||
(Math.abs(delta.x) < threshold.distance &&
Math.abs(delta.y) < threshold.distance)
) {
// 扫太慢或扫的距离太短,不是扫动手势
return;
} else {
// 判断扫动方向
if (Math.abs(delta.x) >= Math.abs(delta.y)) {
// 左右扫动
if (delta.x > 0) {
// 右扫
direction = 'right';
} else {
// 左扫
direction = 'left';
}
} else {
// 上下扫动
if (delta.y > 0) {
// 下扫
direction = 'down';
} else {
// 上扫
direction = 'up';
}
}
cb.call($el, direction);
}
document.removeEventListener('pointerup', endHandler, false);
document.removeEventListener('pointercancel', endHandler, false);
}
}
// swipe(document.getElementById('box'), function (direction) {
// // console.log(this);
// console.log(direction);
// });
swipe(document.getElementById('gesture'), function (direction) {
// console.log(this);
console.log(direction);
});
// 作业:使用 touch 事件模拟扫动手势
// 2.手势库 Hammer.js
// https://hammerjs.github.io/
</script>
</body>
</html>
幻灯片的扫动切换
之前已经实现过了PC幻灯片键盘切换 现在使用Point对幻灯片进行滑动切换
具体代码看本目录 ---> (幻灯片的扫动切换)
import Slider from './slider.js';
const $el = document.querySelector('.slider');
const sliderInstance = new Slider($el);
swipe($el, function (direction) {
if (direction === 'left') {
// 切换下一张
sliderInstance.next();
} else if (direction === 'right') {
// 切换上一张
sliderInstance.prev();
}
});
总结
事件类型
注意事项


特征检测
event对象


阻止浏览器的默认行为
- 阻止scrolling, pinch/zoom,鼠标事件等默认行为