移动端touch事件
- touchstart
- touchmove
- touchend
事件点透
mouse 事件在移动端可以执行,但是要注意点透问题
- 在移动端中,手指触碰时,如果有 touch 事件,会立即执行,
- 并记录触碰坐标,在一定时间延迟后(300ms以内),在该坐标上查找元素,如果元素有mouse事件,就执行。
可以使用
e.preventDefault();
解决box.addEventListener("touchstart",(e)=>{
e.preventDefault();
box.style.display = "none";
})
touchEvent 事件参数
touches 当前屏幕上的手指
- targetTouches 当前元素上的手指
- changedTouches 触发当前事件的手指列表
let box = document.querySelector("#box");
document.addEventListener("touchstart",(e)=>{
e.preventDefault();
},{passive:false})
box.addEventListener("touchmove",(e)=>{
box.innerHTML = `
当前屏幕上的手指个数:${e.touches.length}<br/>
当前元素上的手指个数:${e.targetTouches.length}<br/>
触发当前事件的手指个数:${e.changedTouches.length}
`;
});
划屏操作
和web端的鼠标拖拽是一个思路let wrap = document.querySelector("#wrap");
let list = document.querySelector(".list");
let startPoint = 0;
let startPosition = 0;
let translateY = 0;
wrap.addEventListener("touchstart", (e) => {
console.log(e.changedTouches[0])
startPoint = e.changedTouches[0].pageY;
startPosition = translateY;
});
wrap.addEventListener("touchmove", (e) => {
let nowPoint = e.changedTouches[0].pageY;
let disPoint = nowPoint - startPoint;
translateY = startPosition + disPoint;
list.style.transform = `translateY(${translateY}px)`;
});
划屏的技巧
回弹动画幻灯片
- 当滑动距离超过 wrap.width*threshold 就进行切换,否则还是显示当前张
// ...
let threshold = .3;//当滑动距离超过 wrap.width*threshold 就进行切换,否则还是显示当前张
let wrapW = wrap.clientWidth;
wrap.addEventListener("touchend", (e) => {
// ...
// 判断滑动的距离是多少,大于某个节点时,让它切换到上一张或下一张
if (Math.abs(disPoint.x) > threshold * wrapW) {
//需要进行切换
now -= disPoint.x / Math.abs(disPoint.x);
}
//根据 now 重新计算位置
translateX = -now * wrapW;
list.style.transition = ".3s";
list.style.transform = `translateX(${translateX}px)`;
});
无缝滚动
前后各补一张卡,或者说直接赋值两个图片列表
{
let wrap = document.querySelector("#wrap");
let list = document.querySelector("#list");
let navs = [...document.querySelectorAll(".nav a")];
let startPoint = {};//记录摁下时手指坐标
let startX = 0;//记录摁下时元素位置
let translateX = 0; //记录元素位移值
let now = 0;//记录当前显示的时第几张
let threshold = .3;//当滑动距离超过 wrap.width*threshold 就进行切换,否则还是显示当前张
let wrapW = wrap.clientWidth;
list.innerHTML += list.innerHTML;
wrap.addEventListener("touchstart", (e) => {
list.style.transition = "none";
let touches = e.changedTouches[0];
startPoint = {
x: touches.pageX,
y: touches.pageY
};
if (now === 0) { //第0组的第0张
now = navs.length; //第1组第0张
} else if (now === navs.length * 2 - 1) {//第1组最后一张
now = navs.length - 1;//第0组最后一张;
}
translateX = -now * wrapW;
list.style.transform = `translateX(${translateX}px)`;
startX = translateX;
});
wrap.addEventListener("touchmove", (e) => {
let touches = e.changedTouches[0];
let nowPoint = {
x: touches.pageX,
y: touches.pageY
};
let disPoint = {
x: nowPoint.x - startPoint.x,
y: nowPoint.y - startPoint.y
};
translateX = startX + disPoint.x;
list.style.transform = `translateX(${translateX}px)`;
});
wrap.addEventListener("touchend", (e) => {
let touches = e.changedTouches[0];
let nowPoint = {
x: touches.pageX,
y: touches.pageY
};
let disPoint = {
x: nowPoint.x - startPoint.x,
y: nowPoint.y - startPoint.y
};
// 判断滑动的距离是多少,大于某个节点时,让它切换到上一张或下一张
if (Math.abs(disPoint.x) > threshold * wrapW) {
//需要进行切换
now -= disPoint.x / Math.abs(disPoint.x);
}
//根据 now 重新计算位置
translateX = -now * wrapW;
list.style.transition = ".3s";
list.style.transform = `translateX(${translateX}px)`;
navs.forEach(item => {
item.classList.remove("active");
});
navs[now % navs.length].classList.add("active");
});
}
滑动方向的处理
上下左右滑动可能会产生冲突,设置为只能同时滑动一个方向
- 当用户想要进行左右滑动时,就只是左右可以滑动(禁止上下滑动)
- 当用户,想要进行上下滑动时,把左右滑动禁止了
- 当滑动方向一旦判定,则滑动过程中就一直认定用户想要做该方向的滑动,知道下次再触发滑动时,重新判断。
let isDir = false; // 判断用户是否认定方向
let isMove = true;// 判读是否进行幻灯片切换
wrap.addEventListener("touchmove", (e) => {
// ...
if (!isDir) {
if (Math.abs(disPoint.x) - Math.abs(disPoint.y) > 5) {
//console.log("左右滑动");
isDir = true;
} else if (Math.abs(disPoint.y) - Math.abs(disPoint.x) > 5) {
//console.log("上下滑动");
isDir = true;
isMove = false;
}
}
if (isMove) {
isDir && (translateX = startX + disPoint.x);
isDir && (list.style.transform = `translateX(${translateX}px)`);
e.preventDefault();
}
});
阻止默认事件
如果要给 document、html、body这些元素的touch事件中阻止默认事件,一定记得设置,passive:false (允许阻止默认事件)
let box = document.querySelector("#box");
box.addEventListener("touchstart",(e)=>{
box.style.display = "none";
});
document.body.addEventListener("touchstart",(e)=>{
e.preventDefault();
},{
passive: false
});
阻止 touchstart 默认事件带来的影响
- 默认双指缩放被禁止
- 滚动条被禁止
- 鼠标事件被禁止(包括a标签的href)
- 禁止长按菜单弹出
- 阻止元素获得焦点和失去焦点
阻止 touchmove 默认事件带来的影响
- 默认双指缩放被禁止
- 滚动条被禁止