web移动端触屏事件

1.移动端与pc端的区别

  • (1)移动端没有鼠标,自然也没有鼠标事件。所以onmousedown之类的事件监听在移动端时无效的。
  • (2)移动端为了响应双击事件,onclick事件有300ms的延迟,接下来的300ms内有没有再次点击,有的话视为双击,没有的话视为单击。
  • (3)移动端双击事件:移动端双击时,除了有dblclick事件触发,还有相应的手势效果(放大/缩小),不过不同的浏览器效果不一致。有些浏览器两种特性都支持,有些只支持其中的一种,但是一般最少都支持一种。

下面的代码可以验证当前手机上onclick事件的延迟(在没有设置viewport的时候执行)

 <!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
<script>
    var box = document.querySelector(".box")
    var click_time,touchstart_time,touchend_time
    box.ontouchstart = function(){
        //获取事件触发时的时间戳
        touchstart_time = new Date().getTime()
        console.log('touchstart time = ' + touchstart_time)
    }
    box.ontouchend = function(){
        //获取事件触发时的时间戳
        touchend_time = new Date().getTime()
        console.log('touchend time = ' + touchend_time)
    }
    box.onclick = function(){
        //获取事件触发时的时间戳
        click_time = new Date().getTime()
        console.log('click time = ' + click_time)

        //click一般要晚于touchend事件 我们来看看事件差
        console.log(`与touchstart的时间差${click_time - touchstart_time}`)
        console.log(`与touchend的时间差${click_time - touchend_time}`)
    }
</script>

下面是chrome浏览器手机模式执行时的效果:

下面是火狐浏览器手机模式执行时的效果:

下面是Edge浏览器手机模式执行时的效果:

使用真机测试时记得引入下面的插件,才能查看控制台的输出情况:

<script src="http://cdn.jsdelivr.net/npm/eruda"></script>
<script>
eruda.init();
</script>

IOS13 Safari/chrome/edge/alook/执行效果都差不多,但是无论怎么算click延迟都大于300ms:

总结:click事件的延迟是存在的,但是不同的设备和浏览器计算延迟的方式不一致

下面的代码验证移动端的双击效果(在没有设置viewport的时候执行):

box.ondblclick = function(){
    console.log('dblclick')
}

PC火狐浏览器手机模式(不仅执行dblclick事件,而且有双击放大/缩小的效果):

PC chrome/edge浏览器手机模式(不执行dblclick事件,有双击放大/缩小的效果):

IOS13真机执行效果:
Safari/火狐:能执行dblclick事件,双击放大/缩小。
Edge:能执行dblclick事件,三击放大/缩小(快速点3次)。
chrome:能执行dblclick事件,页面不缩放。
安卓via浏览器:不执行dblclick事件,双击放大/缩小。

2.touch事件

touch事件没有延迟,它是移动端特有的,pc端不支持
他有以下几个事件:
touchstart:开始触屏事件
touchmove:手指滑动事件(持续触发,只touch不滑动不会触发)
touchstend:触屏结束事件
touchcancal:触屏意外中断事件(手机中途来电?)

基本用法:

<script>
    document.addEventListener("touchstart",function(){
        console.log("touchstart")
    })
    document.addEventListener("touchmove",function(){
        console.log("touchmove")
    })
    document.addEventListener("touchend",function(){
        console.log("touchend")
    })
</script>

如果在touchstart中阻止了默认事件,则onlcik事件不会被触发(阻止默认事件不要挂载到document上,浏览器可能不支持)

<script>
    var box = document.querySelector(".box")
    box.addEventListener("touchstart",function(e){
        console.log("touchstart")
        //阻止默认事件,可阻止click事件
        e.preventDefault()
    })
    box.addEventListener("touchmove",function(e){
        console.log("touchmove")
    })
    box.addEventListener("touchend",function(e){
        console.log("touchend")
    })
    box.addEventListener("click",function(e){
        console.log("click")
    })
    box.ondblclick = function(){
        console.log('dblclick')
    }
</script>

PC Chrome浏览器手机模式执行效果(click和dblclick都不执行,且双击时不缩放):

PC 火狐浏览器手机模式执行效果(单击时不执行click和dblclick,):

IOS13手机浏览器执行效果:
Safari/Chrome/火狐/Edge:单击/双击都不执行click和dblclick,页面不缩放(换句话说,能阻止页面缩放和click和dblclick事件)

3.touchEvent事件对象

touchEvent事件对象描述了当前事件中的一系列信息

e.target:触发事件的Dom元素,要注意的是,在同一个touch事件中,用户touch过程产生了滑动,可能touchstart碰触的元素和touchend时元素已经不是同一个,但是他们的e.target依旧指向touchstart中碰触的元素

代码:

效果:

touch事件触发时,可能有一个或多个触点,可以用下面的属性(数组)获取相应的信息:
e.touches:当前屏幕上所有触摸点的列表(只针对touchstart)
e.targetTouches:当前对象上所有触摸点的列表(只针对touchstart)

e.changedTouches:
对于 touchstart 事件, 这个 TouchList 对象列出在此次事件中新增加的触点。
对于 touchmove 事件,列出和上一次事件相比较,发生了变化的触点。
对于touchend事件,changedTouches 是已经从触摸面的离开的触点的集合(也就是说,手指已经离开了屏幕/触摸面)。

每个触点包含下面的属性:
clientX:触摸目标在视口中的x坐标。
clientY:触摸目标在视口中的y坐标。
identifier:标识触摸的唯一ID。
pageX:触摸目标在页面中的x坐标。
pageY:触摸目标在页面中的y坐标。
screenX:触摸目标在屏幕中的x坐标。
screenY:触摸目标在屏幕中的y坐标。
target:触摸的DOM节点目标。

如图:

4.onclick事件延迟的处理

实际开发中300ms的延迟让用户的体验非常不好,我们自然要把延迟去除,而click也涉及到dblclick事件,这里一并测试。

方法一: 更改默认视口宽度为设备宽度

<meta name="viewport" content="width=device-width">

PC Chrome手机模式(click延迟取消,双击不执行dblclick,双击页面不缩放):

PC 火狐手机模式(click延迟取消,双击执行dblclick,双击页面不缩放):

IOS13 真机测试:
Safari/Chrome/Edge/火狐:click大大降低,双击执行dblclick,双击页面不缩放,三击不缩放。

更改默认视口宽度后,click延迟大大降低,在真机测试中,click只比touchend落后40ms左右,dblclic大都能触发。

方法二:fastclick
原理: 在检测到touchend事件的时候,会通过DOM自定义事件立即出发模拟一个click事件,并把浏览器在300ms之后真正的click事件阻止掉(原理应该就是前面所说的在touchstart中阻止默认事件,所以后续的dblclick不会被执行)

屏幕适配方案中,viewport适配需要破坏完美视口,此时配合fastclick可以解决click的延迟问题

步骤:引入fastclick文件,在页面成功加载后,执行FastClick.attach()函数,并传入相应的dom元素

优点:click延迟只有1-2ms,比方法一延迟更低
缺点: 脚本相对较大

<!-- 引入fastclick -->
<script src="https://cdn.bootcss.com/fastclick/1.0.6/fastclick.js"></script>
<script>
    window.onload = function(){
        // 初始化,传入的参数表明整个页面中FastClick都生效
        FastClick.attach(document.body)

        var box = document.querySelector(".box")
        var click_time,touchstart_time,touchend_time
        box.ontouchstart = function(){
            //获取事件触发时的时间戳
            touchstart_time = new Date().getTime()
            console.log('touchstart time = ' + touchstart_time)
        }
        box.ontouchend = function(){
            //获取事件触发时的时间戳
            touchend_time = new Date().getTime()
            console.log('touchend time = ' + touchend_time)
        }
        box.onclick = function(){
            //获取事件触发时的时间戳
            click_time = new Date().getTime()
            console.log('click time = ' + click_time)

            //click一般要晚于touchend事件 我们来看看事件差
            console.log(`与touchstart的时间差${click_time - touchstart_time}`)
            console.log(`与touchend的时间差${click_time - touchend_time}`)
        }
        box.ondblclick = function(){
            console.log('dblclick')
        }
    }
</script>

fastclick使click延迟会降低至1-2ms,安卓via依旧触发dblclick,而ios13一众浏览器都不触发

5.click与dblclick事件总结

(1)未设置视口宽度时,click事件存在300ms的延迟,而dblclick事件有些浏览器不能触发(安卓via)

(2)设置视口宽度为设备名宽度后,click时间延迟降低,降低幅度可能取决于系统。在ios13中多数浏览器都还有40ms,而安卓via只有7-8ms。ios13和安卓via都能触发dblclick事件,视口宽度不是设备宽度则不行。

(3)在touchstart事件中阻止默认事件后,ios13一众浏览器都不触发click和dblclick事件,包括安卓via。

(4)使用fastclick一般配合viewport适配,安卓via依旧触发dblclick,而ios13一众浏览器都不触发。

posted @ 2019-10-03 23:40  ---空白---  阅读(874)  评论(0编辑  收藏  举报