H5监听移动设备摇一摇功能实现[转]



<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title>摇一摇</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>
    <button id="startBtn">开启摇一摇</button>
    <button id="closeBtn">关闭摇一摇</button>
    <script>
        /*
        setDeviceMotion 添加陀螺仪监控
        参数: cb devicemotion的事件处理函数; errCb 不支持devicemotion时的处理回调
        */
        function setDeviceMotion(cb, errCb) {
            if (!window.DeviceMotionEvent) {
                errCb("设备不支持DeviceMotion");
                return;
            }
            if (typeof DeviceMotionEvent.requestPermission === 'function') {
                // IOS13 设备
                DeviceMotionEvent.requestPermission()
                .then(permissionState => {
                    if (permissionState === 'granted') {
                        window.addEventListener('devicemotion', cb);
                    }
                })
                .catch((err) => {
                    errCb("用户未允许权限");
                });
            } else {
                // 其他支持加速度检测的系统
                let timer = setTimeout(function () {
                    errCb("用户未开启权限");
                }, 1000);
                window.addEventListener("devicemotion", (e) => {
                    clearTimeout(timer);
                }, { once: true });
                window.addEventListener("devicemotion", cb);
            }
        }

        /*
        throttle 节流函数
        参数:
        fn 要节流的函数
        interval 节流间隔时间
        start 是否在节流开始时执行 (true在开始时执行,false在结束时执行)
        返回值:
        经过节流处理的函数
        */
        function throttle(fn, interval = 200, start = true) {
            if (typeof fn !== "function") {
                return console.error("请传入一个函数");
            }
            let timer = 0;
            return function (...arg) {
                let _this = this;
                if (timer) {
                    return;
                }
                start && fn.apply(_this, arg);
                timer = setTimeout(() => {
                    (!start) && fn.apply(_this, arg);
                    timer = 0;
                }, interval);
            }
        }

        /*
        addShake 添加摇一摇功能
        参数:cbShake 类型 fn 当用户进行了摇一摇之后要做的事情
        返回值:shakeIndex 开启的第几个摇一摇功能的索引,用来删除监听    
        */
        function addShake(cbShake) {
            const maxRange = 60; //当用户的两次加速度差值大于这个幅度,判定用户进行了摇一摇功能
            const minRange = 10; //当用户的两次加速度差值小于这个幅度,判定用户停止摇动手机
            let isShake = false; //记录用户是否摇动手机
            let lastX = 0,lastY = 0,lastZ = 0;
            function toShake(e) {
                let motion = e.acceleration;
                let {x, y, z} = motion;
                let range = Math.abs(x - lastX) + Math.abs(y - lastY) + Math.abs(z - lastZ);
                if (range > maxRange) {//用户进行了摇一摇
                    isShake = true;
                }
                if (range < minRange && isShake) { // 停止摇一摇
                    cbShake(e);
                    isShake = false;
                }
                lastX = x;
                lastY = y;
                lastZ = z;
            }
            if (!window.shakeEvent) { //建立 shakeEvent 存储所有的摇一摇的处理函数,方便一会取消
                window.shakeEvent = [];
            }
            toShake = throttle(toShake);
            window.shakeEvent.push(toShake);
            setDeviceMotion(toShake, (errMessage) => {
                alert(errMessage)
            })
            return window.shakeEvent.length - 1;//返回该次摇一摇处理的索引
        }

        /*
        删除摇一摇监听
        参数:shakeIndex 摇一摇功能的索引
        */
        function removeShake(shakeIndex) {
            window.removeEventListener("devicemotion", window.shakeEvent[shakeIndex]);
        }

        // 调用摇一摇
        {
            let startBtn = document.querySelector("#startBtn");
            let closeBtn = document.querySelector("#closeBtn");
            let isStartShake = false;
            let shakeIndex;
            // 再次强调 IOS 13.3 需要用户触发,再能开启摇一摇
            startBtn.addEventListener("touchend", () => {
                if (isStartShake) return;
                isStartShake = true;
                shakeIndex = addShake(() => {
                    alert("您进行了摇一摇!")
                })
            });
            closeBtn.addEventListener("touchend", () => {
                if (!isStartShake) return;
                isStartShake = false;
                removeShake(shakeIndex);
            });
        }
    </script>
</body>
</html>

原文链接

[1].H5设备运动事件 DeviceMotionEvent 实现摇一摇功能:https://www.jianshu.com/p/a0d671f723cb

上一篇: Javascript节流函数
下一篇: WinRAR6.11去除弹窗广告图解
文章来自: 简书
引用通告: 查看所有引用 | 我要引用此文章
Tags:
最新日志:
评论: 0 | 引用: 0 | 查看次数: 812
发表评论
登录后再发表评论!