移动端事件

移动端的常见事件

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>

解决办法

  1. 换成移动端事件
 oSpan.addEventListener('touchend', function(){
    alert(1);
}, false);
  1. 阻止pc的事件

//猜想(pc的事件应该都算默认行为) 
document.addEventListener('touchstart', function(ev){
    ev.preventDefault();
}, false);

这是你注册的click事件, 永远都不会触发, a标签也不会跳转,

touch所有类型事件都会冒泡,如果阻止了touchstart的默认行为,后续的mousedown和click事件将不会触发

阻止了touchmove的默认行为,后续的mousemove事件将不会触发

如果阻止了touchend的默认行为,后续的mouseup和click事件将不会触发

同时解决了:

  1. IOS10下设置meta禁止用户缩放是不可行的。(使用阻止pc事件就可以在IOS10下禁止用户缩放)

  2. 解决IOS10下溢出隐藏的问题。

  3. 禁止系统默认的滚动条、阻止橡皮筋效果

  4. 禁止长按选中文字、选中图片、系统默认菜单

  5. 解决点透问题

  6. 也阻止了焦点元素的焦点行为(要正常使用: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;
    ....
})

推荐阅读更多精彩内容