移动端h5监测图片长按保存操作实践

在做项目的时候我们都会多多少少写一些监测代码 ,之前也是遇到了一个比较搞的需求,大概就是我需要监测用户长按保存图片,我发现浏览器似乎没有原生提供这样一个API,没办法只能自己模拟写一个了,在实现的过程中也是踩了一些奇奇怪怪的坑,比如说安卓和苹果的表现是不一样的

好了话不多说先看实现效果:

核心代码如下:

ts 复制代码
// 判断是否是IOS设备
const isIos = (): boolean => /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream

// 监测用户图片长按保存操作
const useMonitorImgPressSave = (imgSelectorName: string, callback: () => void) => {

    try {

        /** 类型判断 */
        if (typeof imgSelectorName !== "string") {

            throw 'imgSelectorName 需要传 "string" 类型'

        }
        /** 类型判断 */
        if (typeof callback !== "function") {

            throw 'callback 需要传 "function" 类型'

        }

        const _imgDom = <HTMLImageElement>document.querySelector(imgSelectorName) ?? null
        /** 如果未找到dom元素 */
        if (!_imgDom) {

            throw `没有找到 "${imgSelectorName}" 选择器的dom元素`

        }
        /** 如果不是图片元素 */
        if (!(_imgDom instanceof HTMLImageElement)) {

            throw '不是一个 "图片" 元素,只能接受图片'

        }

        let _touchstartCallback: () => void, _touchendCallback: () => void

        /** FUN: 删除触摸监听 */
        const _imgDomRemoveEventListener = () => {

            _imgDom.removeEventListener("touchstart", _touchstartCallback)
            _imgDom.removeEventListener("touchend", _touchendCallback)

        }

        /** FUN: 设置安卓触摸 */
        const _setAndroidTouchMonitorEvent = () => {

            // 长按定时器
            let _pressTimer: any

            _touchstartCallback = () => {

                console.log("安卓触摸开始")

                clearTimeout(_pressTimer)
                _pressTimer = setTimeout(() => {

                    clearTimeout(_pressTimer)
                    /** 执行监测代码 */
                    callback()
                    _imgDomRemoveEventListener()

                }, 800)

            }

            _touchendCallback = () => {

                console.log("安卓触摸结束")
                clearTimeout(_pressTimer)
                _imgDomRemoveEventListener()

            }

            // 添加长按保存事件监听器(触摸开始)
            _imgDom.addEventListener("touchstart", _touchstartCallback)
            // 添加长按保存事件监听器(触摸结束)
            _imgDom.addEventListener("touchend", _touchendCallback)

        }

        /** FUN: 设置IOS触摸 */
        const _setIosTouchMonitorEvent = () => {

            // 长按开始时间
            let _pressStartTime: any

            _touchstartCallback = () => {

                console.log("苹果触摸开始")

                // ios环境下H5长按保存图片会造成图片悬浮,可以取消默认事件去除这种效果,并不阻止下拉菜单的弹出(注意:微信环境下没有问题,其他APP环境下无法保存)
                // 踩坑:如果是企业微信环境下,需要注释这条代码,否则ios无法长按保存图片
                // isWx() && event.preventDefault()
                _pressStartTime = Date.now()

            }

            _touchendCallback = () => {

                console.log("苹果触摸结束")
                /** 长按时间大于800毫秒执行监测代码 */
                Date.now() - _pressStartTime > 800 && callback()
                _imgDomRemoveEventListener()

            }

            // 添加长按保存事件监听器(触摸开始)
            _imgDom.addEventListener("touchstart", _touchstartCallback)
            // 添加长按保存事件监听器(触摸结束)
            _imgDom.addEventListener("touchend", _touchendCallback)

        }

        /** 由于安卓跟苹果的差异,当用户长按图片保存菜单弹出时,安卓不会触发touchend事件,苹果会,所以这里分2套 */
        isIos() ? _setIosTouchMonitorEvent() : _setAndroidTouchMonitorEvent()

    }
    catch (error) {

        console.error("useMonitorImgPressSave()", error)

    }

}

使用示例:

vue 复制代码
<script setup lang="ts">
onMounted(() => {

    useMonitorImgPressSave(".vue", () => {

        console.log("图片已保存")

    })

})
</script>

<template>
    <img class="vue" src="../assets/image/logo/vue.svg" />
</template>

希望能够给大家带来帮助!

相关推荐
lh_125418 分钟前
ECharts 地图开发入门
前端·javascript·echarts
jjw_zyfx19 分钟前
成熟的前端vue vite websocket,Django后端实现方案包含主动断开websocket连接的实现
前端·vue.js·websocket
Mikey_n1 小时前
前台调用接口的方式及速率对比
前端
周之鸥1 小时前
使用 Electron 打包可执行文件和资源:完整实战教程
前端·javascript·electron
我爱吃朱肉1 小时前
HTMLCSS模板实现水滴动画效果
前端·css·css3
机器视觉知识推荐、就业指导1 小时前
开源QML控件:进度条滑动控件(含源码下载链接)
前端·qt·开源·qml
前端snow1 小时前
前端全栈第二课:用typeorm向数据库添加数据---一对多关系
前端·javascript
難釋懷1 小时前
Shell脚本-for循环语法结构
前端·chrome
全栈老李技术面试2 小时前
【高频考点精讲】async/await原理剖析:Generator和Promise的完美结合
前端·javascript·css·vue·html·react·面试题
kadog2 小时前
PubMed PDF下载 cloudpmc-viewer-pow逆向
前端·javascript·人工智能·爬虫·pdf