前言
手机应用一般都会提供原生的摇一摇功能,但是由于系统的差异性,H5 想要实现摇一摇功能,没法统一调用系统所提供的原生接口,便需要额外监听浏览器的事件。今天便将实现 H5 摇一摇功能的问题记录下来,方便以后学习查看。
实现原理
devicemotion
devicemotion 事件每隔一定时间触发一次,显示设备当时在包括/不包括重力的作用下的加速度大小。如果有的话,它还会提供有关旋转速率的信息。
该事件不可取消,也不会冒泡。
属性
DeviceMotionEvent.acceleration
给出设备在 x、y、z 三轴上的加速度。加速度用 m/s² 表示。
DeviceMotionEvent.accelerationIncludingGravity
在重力作用下,给出设备在 x、y、z 三个轴上的加速度的对象。加速度单位为 m/s²。
DeviceMotionEvent.rotationRate
一个给出设备绕三个方向轴(阿尔法轴、贝塔轴和伽马轴)的旋转速率的对象。旋转速率以度每秒表示。
DeviceMotionEvent.interval
代表从设备获取数据的时间间隔(毫秒)的数字。
!!!注意点
在 iOS 设备上使用 devicemotion 事件时,确实需要获取用户的权限。iOS 13 及更高版本要求应用在访问设备的运动和方向传感器时,必须请求用户的许可。
可以通过在 JavaScript 中调用 DeviceMotionEvent.requestPermission() 方法来请求权限。
实现步骤
- 请求权限:在设备上请求访问设备的运动和方向传感器的权限。
- 监听 devicemotion 事件:在组件中使用 useEffect 钩子监听设备的加速度变化。
- 检测摇动:通过计算加速度的变化来检测摇动。
- 记录摇动次数:每次检测到摇动时,增加摇动次数。
react 实现代码
useShake
import {
useCallback, useEffect, useMemo, useState } from 'react';
declare const DeviceMotionEvent: DeviceMotionEvent;
export const useShake = (
threshold = 15, // sensitivity threshold for shake detection
resetTime = 160, // time to wait before detecting the next shake
) => {
const [shakeCount, setShakeCount] = useState<number>(0);
const [isListening, setIsListening] = useState<boolean>(false);
useEffect(() => {
let lastX = 0;
let lastY = 0;
let lastZ = 0