记录--移动端的双击事件好不好用?

这篇具有很好参考价值的文章主要介绍了记录--移动端的双击事件好不好用?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

记录--移动端的双击事件好不好用?

前言

2023年了,我不允许还有人不会自己实现移动端的双击事件。

过来,看这里,不足 50 行的代码实现的双击事件。

听笔者娓娓道来。

dblclick

js原生有个dblclick双击事件,但是几乎不支持移动端。

记录--移动端的双击事件好不好用?

 而且,该dblclick事件在pc端鼠标双击时,会触发两次click与一次dblclick

window.addEventListener('click', () => {
    console.log('click')
});
window.addEventListener('dblclick', () => {
    console.log('dblclick')
});

// 双击页面,打印:click✖️2 dblclick

我们期望可以在移动端也能有双击事件,并且隔离单击与双击事件,双击时只触发双击事件,只执行双击回调函数,让注册双击事件像注册原生事件一样简单。

点击穿透

简单聊聊移动端的点击穿透。

在移动端单击会依次触发touchstart->touchmove->touchend->click事件。

有这样一段逻辑,在touchstart时出现全屏弹框,在click弹框时关闭弹框。实际上,在点击页面时,弹框会一闪而过,并没有出现正确的交互。在移动端单击时touchstart早于click,当弹框出现了,后来的click事件就落在了弹框上,导致弹框被关闭。这就是点击穿透的一种表现。

笔者的业务需求是双击元素,出现全屏弹框,单击弹框时关闭弹框。因此基于这样的业务需求与现实的点击穿透问题,笔者选择采用click事件来模拟双击事件,并且适配pc端使用。大家也可以选择解决点击穿透问题,并采用touchstart模拟双击事件,可以更快地响应用户操作。

采用touchstart模拟时,可以再考虑排除双指点击的情况。

在实现上与下文代码除了事件对象获取位置属性有所不同外,其它代码基本一致,实现思路无差别。

模拟双击事件

采用click事件来模拟实现双击。

双击事件定义:2次点击事件间隔小于200ms,并且点击范围小于10px的视为双击。这里的双击事件是自定义事件,为了区分原生的 dblclick,又优先满足移动端使用,则事件名定义为 dbltouch,后续可以使用window.addEventListener('dbltouch', ()=>{})来监听双击事件。

这个间隔与位移限制大家可以根据自己的业务需求调整。通常采用的是300ms的间隔与10px的位移,笔者业务中发现200ms间隔也可使用。

自定义事件名大家可以随意设置,满足语义化即可。

  1. 监听click事件,并在捕获阶段监听,目的是为了后续能够阻止click事件传播。

window.addEventListener('click', handler, true);

监听函数中,第1次点击时,记录点击位置,并设置200ms倒计时。如果第2次点击在200ms后,则重新派发当前事件,让事件继续传播,使其它的监听函数可以继续处理对应事件。

// 标识是否在等待第2次点击
let isWaiting = false;

// 记录点击位置
let prevPosition = {};

function handler(evt) {
    const { pageX, pageY } = evt;
    prevPostion = { pageX, pageY };
    // 阻止冒泡,不让事件继续传播
    evt.stopPropagation();
    // 开始等待第2次点击
    isWaiting = true;
    // 设置200ms倒计时,200ms后重新派发当前事件
    timer = setTimeout(() => {
        isWaiting = false;
        evt.target.dispatchEvent(evt);
    }, 200)
}

注意: 倒计时结束时evt.target.dispatchEvent(evt)派发的事件仍是原来的事件对象,即仍是click事件,会触发继续handler函数,进入了循环。

这里需要破局,已知Event事件对象下有一个 isTrusted 属性,是一个只读属性,是一个布尔值。当事件是由用户行为生成的时候,这个属性的值为 true ,而当事件是由脚本创建、修改、通过 EventTarget.dispatchEvent()派发的时候,这个属性的值为 false 。

因此,此处脚本派发的事件是希望继续传递的事件,不用handler内处理。

function handler(evt) {
    // 如果事件是脚本派发的则不处理,将该事件继续传播
    if(!evt.isTrusted){
        return;
    }
}

处理完第1次点击后,接着处理在200ms内的第2次点击事件。如果满足位移小于10px的条件,则视为双击。

// 标识是否在等待第2次点击
let isWaiting = false;

// 记录点击位置
const prevPosition = {};

function handler(evt) {
    // 如果事件是脚本派发的则不处理,将该事件继续传播
    if(!evt.isTrusted){
        return;
    }
    const { pageX, pageY } = evt;
    if(isWaiting) {
        isWaiting = false;
        const diffX = Math.abs(pageX - prevPosition.pageX);
        const diffY = Math.abs(pageY - prevPosition.pageY);
        // 如果满足位移小于10,则是双击
        if(diffX <= 10 && diffY <= 10) {
            // 取消当前事件传递,并派发1个自定义双击事件
            evt.stopPropagation();
            evt.target.dispatchEvent(
                new PointerEvent('dbltouch', {
                    cancelable: false,
                    bubbles: true,
                })
            )
        }
    } else {
        prevPostion = { pageX, pageY };
        // 阻止冒泡,不让事件继续传播
        evt.stopPropagation();
        // 开始等待第2次点击
        isWaiting = true;
        // 设置200ms倒计时,200ms后重新派发当前事件
        timer = setTimeout(() => {
            isWaiting = false;
            evt.target.dispatchEvent(evt);
        }, 200)
    }
}

以上便实现了双击事件,全局任意地方监听双击。

window.addEventListener('dbltouch', () => {
    console.log('dbltouch');
})
window.addEventListener('click', () => {
    console.log('click');
})
// 使用鼠标、手指双击
// 打印出 dbltouch
// 而且不会打印有click

笔者要在这里说句 但是: 由于200ms的延时,虽不多,但是对于操作迅速的用户来讲,还是会有不好的体验。

优化双击事件

由于是在window上注册的click函数,虽说注册双击事件像单击事件一样简单了,但却也导致整个产品页面的click事件都会推迟200ms执行。

因此,我们应该只对需要处理双击的地方添加双击事件,至少只在局部发生延迟情况。稍微调整下代码,将需要注册双击事件的元素由开发决定,通过参数传递。而且事件处理函数也可以通过参数传递,即可以通过监听双击事件,也可以通过回调函数执行。

以下是完整的代码。

class RegisterDbltouchEvent {
    constructor(el, fn) {
        this.el = el || window;
        this.callback = fn;
        this.timer = null;
        this.prevPosition = {};
        this.isWaiting = false;
        
        // 注册click事件,注意this指向
        this.el.addEventListener('click', this.handleClick.bind(this), true);
    }
    handleClick(evt){
        if(this.timer) {
            clearTimeout(this.timer);
            this.timer = null;
        }
        if(!evt.isTrusted) {
            return;
        };
        if(this.isWaiting){
            this.isWaiting = false;
            const diffX = Math.abs(pageX - this.prevPosition.pageX);
            const diffY = Math.abs(pageY - this.prevPosition.pageY);
            // 如果满足位移小于10,则是双击
            if(diffX <= 10 && diffY <= 10) {
                // 取消当前事件传递,并派发1个自定义双击事件
                evt.stopPropagation();
                evt.target.dispatchEvent(
                    new PointerEvent('dbltouch', {
                        cancelable: false,
                        bubbles: true,
                    })
                );
                // 也可以采用回调函数的方式
                this.callback && this.callback(evt);
            }
        } else {
            this.prevPostion = { pageX, pageY };
            // 阻止冒泡,不让事件继续传播
            evt.stopPropagation();
            // 开始等待第2次点击
            this.isWaiting = true;
            // 设置200ms倒计时,200ms后重新派发当前事件
            this.timer = setTimeout(() => {
                this.isWaiting = false;
                evt.target.dispatchEvent(evt);
            }, 200)
        }
    }
}

只为需要实现双击逻辑的元素注册双击事件。可以通过传递回调函数的方式执行业务逻辑,也可以通过监听dbltouch事件的方式,也可以同时使用,it's up to you.

const el = document.querySelector('#dbltouch');
new RegisterDbltouchEvent(el, (evt) => {
    // 实现双击逻辑
})

本文转载于:

https://juejin.cn/post/7274043371731796003

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 记录--移动端的双击事件好不好用?文章来源地址https://www.toymoban.com/news/detail-693744.html

到了这里,关于记录--移动端的双击事件好不好用?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • iMazing3安全吗?好不好用?值不值得下载

    一、安全性 iMazing在设计和开发过程中,始终把用户数据的安全性放在首位。它采用了多种先进的安全技术来确保用户数据在传输、备份和存储过程中的安全。 iMazing3Mac-最新绿色安装包下载如下: https://wm.makeding.com/iclk/?zoneid=49816 iMazing3Win-最新绿色安装包下载如下: https://w

    2024年03月08日
    浏览(63)
  • 腾讯云AI绘画好不好用,与同类产品对比有何优势?来看看ChatGPT是如何回答的。

    最近有不少开发者来咨询,那么多AI绘画平台,该如何选择? 既要性价比又要效果好,还能有保障,大厂当然是首选,毕竟算法、算力、储存与服务有足够的保障。 有开发者问腾讯云的AI绘画怎么样? 秉持中立的原则,笔者试着把这个问题交给ChatGPT来回答。 在官网查询到,

    2024年02月15日
    浏览(63)
  • js 实现双击事件

    背景:使用uniapp vue开发小程序时,需要实现按钮双击事件 思路:通过给按钮绑定单击事件,然后定义一个数组记录每次单击的按钮标识和单击的时间戳,然后每次单击后比较数组最后两个元素,如果最后两个元素dom标识为同一个dom并且时间差值小于500ms,则判定为双击事件,

    2024年02月13日
    浏览(30)
  • antd table的单击事件和双击事件冲突

    问题:当table上同时有onClick和onDoubleClick时,双击会一直触发单击事件。 解决方法:使用延迟定时器-setTimeout                   单击事件延迟执行,如果检测到连续点击,则是双击事件,不再执行单击事件。 代码实现:

    2024年01月25日
    浏览(57)
  • Qt实现鼠标双击事件

    当同一个部件既要响应鼠标单击事件又要响应鼠标双击事件时,就会发生冲突,如下例: 创建自己的按钮类,让其继承于QPushButton类 (特别注意!!!) ,在创建类的时候默认可供选择的基类中无QPushButton类且没有QPushButton类的基类,无法使用多重继承,故必须手动修改继承

    2024年02月10日
    浏览(42)
  • Unity 单击、双击、长按事件处理

    想要一个工具,能够同时集成单击、双击、长按的功能 通过IPointerDownHandler, IPointerUpHandler, IPointerClickHandler这三个接口就可以监听点击状态,然后再通过不同的点击状态来处理相应的事件 由于可能同时存在多个事件,实际开发过程中会出现多余事件通知,如下: 同时拥有单击

    2024年02月11日
    浏览(56)
  • Android双击图片放大移动图中双击点到ImageView区域中心,Kotlin

      初始化状态,ImageView里面只是显示一张fitcenter被缩放的原图,当手指在图片上双击后(记录双击点位置:mCurX,mCurY)画一个红色小圆圈标记双击位置,放大图片,然后把放大后的图的(原mCurX,mCurY)位置移动到区域中心点位置,用大的红色圆圈标记。   双击:     放大图

    2024年01月21日
    浏览(47)
  • 给大家介绍几个手机冷门但好用的小技巧

    技巧一:拍照识别植物 手机的拍照识别植物功能是指在使用手机相机时,可以通过对植物进行拍照,并通过植物识别技术,获取植物的相关信息和资料。其主要优点如下: 方便实用:使用拍照识别植物功能,用户只需对植物进行拍照即可获取相关信息,方便快捷。 资料齐全

    2024年02月01日
    浏览(94)
  • QT6实现按钮双击事件

    实现思路:利用事件过滤器实现按钮双击功能,主要是通过调用installEventFilter函数和重写事件eventFilter函数实现。   1、创建项目 启动Qt Creator,在主菜单的[文件]下,打开[新建文件或项目]菜单,弹出新建文件或项目对话框,创建Qt Widgets Application 项目,在Class Information步骤中

    2024年02月12日
    浏览(44)
  • 今天跟大家分享好用的智能ai绘画免费软件有哪些

    在教学的时候配合进行ai绘画操作来讲解日常的知识,可以帮助学生更好的理解,比如在讲解化学反应的时候,我们可以通过文字描述反应的化学式和反应过程,但是这可能会让学生感到无趣和枯燥,知识没办法真正的进入大脑。而如果借助ai绘画的软件,我们可以将反应的过

    2024年02月12日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包