移动端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>

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

相关推荐
sunshine6412 分钟前
【CSS】实现tag选中对钩样式
前端·css·css3
真滴book理喻26 分钟前
Vue(四)
前端·javascript·vue.js
蜜獾云28 分钟前
npm淘宝镜像
前端·npm·node.js
dz88i828 分钟前
修改npm镜像源
前端·npm·node.js
Jiaberrr32 分钟前
解锁 GitBook 的奥秘:从入门到精通之旅
前端·gitbook
顾平安2 小时前
Promise/A+ 规范 - 中文版本
前端
聚名网2 小时前
域名和服务器是什么?域名和服务器是什么关系?
服务器·前端
桃园码工2 小时前
4-Gin HTML 模板渲染 --[Gin 框架入门精讲与实战案例]
前端·html·gin·模板渲染
不是鱼2 小时前
构建React基础及理解与Vue的区别
前端·vue.js·react.js
沈剑心2 小时前
如何在鸿蒙系统上实现「沉浸式」页面?
前端·harmonyos