移动端的常见事件
touchstart 手指按下时触发
touchmove 手指移动
touchend 手指抬起
<div></div>
<p></p>
<script>
var oDiv = document.querySelector('div');
var oP = document.querySelector('p');
//最好不要用on的方式, 在chrome 模拟器下时好时坏
oDiv.addEventListener('touchstart', function(){
oP.innerHTML += '按下';
}, false);
oDiv.addEventListener('touchmove', function(){
oP.innerHTML += '移动';
}, false);
oDiv.addEventListener('touchend', function(){
oP.innerHTML += '抬起';
}, false);
</script>
pc端的事件在移动端的问题
pc上的事件比移动端的事件略慢, 大概在300ms左右
oDiv.addEventListener('mouseup', function(){
oP.innerHTML += '鼠标抬起 ';
}, false);
oDiv.addEventListener('touchend', function(){
oP.innerHTML += '抬起 ';
}, false);
每次点击, 都是抬起 鼠标抬起
注意不要:移动手指, 移动之后就不会触发mouseup事件了
移动端的点透
<style>
div{
height: 200px;
width: 200px;
background: rgba(99, 99, 99, 0.5);
position: absolute;
top: 0;
}
</style>
<span>span, 点击我</span>
<div>
<script>
var oDiv = document.querySelector('div');
var oSpan = document.querySelector('span');
oDiv.addEventListener('touchend', function(){
this.style.display = 'none';
}, false);
oSpan.addEventListener('click', function(){
alert(1);
}, false);
</script>
效果是点击div,手指抬起div消失
但是,当你点到div上span标签的位置,会触发span的click事件,div是覆盖了span标签的
span标签应该是点不到的, 如果将div的背景设为实色, 根本就看不到span标签
这就是移动端的点透问题:
当两个元素重叠时,当上层元素发生点击, 并且下层元素也有点击(焦点)特性,
如果在300ms之内, 上层元素消失, 目标点就会到下层元素, 触发下层元素的点击行为
所以如果你点击div300毫秒之后才抬起手指, 也不会触发span的click事件
原因就是因为pc上的事件比移动端的事件的300ms延迟
关于a标签,也会发生上面的点透问题
<style>
div{
height: 200px;
width: 200px;
background: rgba(99, 99, 99, 0.5);
position: absolute;
top: 0;
}
</style>
<a href="/">a标签</a>
<div>
<script>
var oDiv = document.querySelector('div');
oDiv.addEventListener('touchend', function(){
this.style.display = 'none';
}, false);
</script>
解决办法
- 换成移动端事件
oSpan.addEventListener('touchend', function(){
alert(1);
}, false);
- 阻止pc的事件
//猜想(pc的事件应该都算默认行为)
document.addEventListener('touchstart', function(ev){
ev.preventDefault();
}, false);
这是你注册的click事件, 永远都不会触发, a标签也不会跳转,
touch所有类型事件都会冒泡,如果阻止了touchstart的默认行为,后续的mousedown和click事件将不会触发
阻止了touchmove的默认行为,后续的mousemove事件将不会触发
如果阻止了touchend的默认行为,后续的mouseup和click事件将不会触发
同时解决了:
IOS10下设置meta禁止用户缩放是不可行的。(使用阻止pc事件就可以在IOS10下禁止用户缩放)
解决IOS10下溢出隐藏的问题。
禁止系统默认的滚动条、阻止橡皮筋效果
禁止长按选中文字、选中图片、系统默认菜单
解决点透问题
也阻止了焦点元素的焦点行为(要正常使用:ev.stopPropagation()阻止冒泡)
移动端的事件对象
touchs
当前位于屏幕上的所有手指的一个列表
targetTouches
位于当前DOM元素上的手指的一个列表
changedTouches
涉及当前事件的手指的一个列表
<style>
div{
height: 100px;
width: 100px;
background: red;
}
</style>
<div></div>
<script>
var div = document.querySelector('div');
div.addEventListener('touchmove', function(ev){
//只要我有几个手指在屏幕上, 就会显示几
// div.innerHTML = ev.touches.length;
})
</script>
例子:轮播图
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<style>
*{
margin: 0;
padding: 0;
}
.container{
width: 100%;
height: 321px;
overflow: hidden;
position: relative;
}
.wrap{
position: absolute;
width: 100%;
white-space: nowrap;
font-size: 0;
left: 0;
}
img{
width: 100%;
display: inline-block;
}
</style>
</head>
<body>
<div class="container">
<div class="wrap">
![](1.jpg)
![](2.jpg)
![](3.jpg)
![](4.jpg)
</div>
</div>
<script>
document.addEventListener('touchstart', function(ev){
ev.preventDefault();
})
var wrap = document.querySelector('.wrap');
var img = document.querySelector('img');
var width = img.offsetWidth;
wrap.addEventListener('touchstart', function(ev){
// 需要去掉过渡效果,因为会跟移动产生冲突,造成卡顿
wrap.style.transition = 'none';
//移动端只需加webkit前缀
wrap.style.webkitTransition = 'none';
var e = ev.changedTouches[0];
var disX = e.pageX;
var left = this.offsetLeft;
wrap.addEventListener('touchmove', function(ev){
var e = ev.changedTouches[0];
this.style.left = left + (e.pageX - disX) + 'px';
});
wrap.addEventListener('touchend', function(ev){
var e = ev.changedTouches[0];
left = this.offsetLeft;
var num = Math.round(left/width);
wrap.style.transition = '1s';
//移动端只需加webkit前缀
wrap.style.webkitTransition = '1s';
wrap.style.left = num*width+'px';
})
});
</script>
</body>
</html>
无缝滚动, 复制相同的img, 如果你本来有4张图片, 那么现在就有8张
如果点toucnstart到第一张, 迅速跳的第5张, 如果点toucnstart到第8张, 迅速跳的第4张,
wrap.addEventListener('touchstart', function(ev){
....
num = Math.round(left/width);
if(num==0){
num = -length;
}
if(-num==2*length-1){
num = -(length-1);
}
this.style.left = num*width + 'px';
left = this.offsetLeft;
....
})