免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

使用 useAnimatedSensor 打造基于设备传感器的 React Native 交互动画

使用 useAnimatedSensor 打造基于设备传感器的 React Native 交互动画 使用 useAnimatedSensor 打造基于设备传感器的 React Native 交互动画【免费下载链接】react-native-reanimatedReact Natives Animated library reimplemented项目地址: https://gitcode.com/GitHub_Trending/re/react-native-reanimated导读useAnimatedSensor是 React Native Reanimatedv2.5.0 起提供内置的传感器 Hook让开发者可以基于陀螺仪、加速度计、重力、磁场与旋转矢量等设备传感器数据直接在 UI 线程上驱动流畅的交互动画。本文将系统讲解它的完整 API、传感器类型与配置项、返回值的数据结构、底层实现原理与实战示例帮助你快速掌握从传感器读数到动画渲染的完整链路。注意本文基于当前仓库version-2.x的文档快照编写不同大版本 API 可能存在差异。一、useAnimatedSensor 是什么在 React Native 应用中设备传感器如陀螺仪 Gyroscope、加速度计 Accelerometer持续产生高频原始数据。传统做法是把这些数据桥接回 JS 线程再做处理而 Reanimated 的思路是传感器数据以 SharedValue 的形式直接写入 UI 线程动画工作区worklet可以直接读取并驱动withTiming、withSpring等动画省去了跨线程通信开销。useAnimatedSensor的签名如下见 Hook 源码useAnimatedSensor(sensorType: [SensorType], config?: [UserConfig]) - [AnimatedSensor]sensorType必填从SensorType枚举中选择要使用的传感器config可选用于定制传感器行为的配置对象UserConfig返回值一个AnimatedSensor实例包含传感器读数SharedValue、注销函数、可用性标志与配置。从源码看该 Hook 内部通过useMemo把用户配置与默认值合并然后在useEffect中调用registerSensor完成注册并在组件卸载时自动调用unregister清理见 useAnimatedSensor.ts。这意味着你无需手动管理传感器生命周期——组件卸载即自动释放。二、传感器类型 SensorType 枚举SensorType定义于 commonTypes.ts当前支持 5 种传感器前四种输出3DVectorROTATION输出RotationVector枚举值输出类型单位/含义ACCELEROMETER3DVector加速度m/s²不含重力GYROSCOPE3DVector角速度rad/sGRAVITY3DVector重力矢量m/s²MAGNETIC_FIELD3DVector磁场强度μT微特斯拉ROTATIONRotationVector旋转矢量四元数 欧拉角ROTATION 传感器的特殊输出ROTATION是功能最丰富的传感器其RotationVector同时包含归一化四元数与欧拉角两组表示[qx, qy, qz, qw]归一化四元数quaternion[yaw, pitch, roll]绕各轴的旋转角单位为弧度iOS 上遵循 Apple 的 Core Motion 约定参考文档即 yaw 对应绕 z 轴水平朝向角、pitch 对应绕 x 轴俯仰角、roll 对应绕 y 轴侧倾角。从 useAnimatedSensor.ts 可以看到内部还通过eulerToQuaternionworklet 函数参考 three.js 的 Quaternion 实现欧拉角顺序为 ZXY把欧拉角换算为四元数保证两种表示始终一致。三、配置项 UserConfig 详解config参数的类型为UserConfig源码中称SensorConfig见 commonTypes.ts包含三个字段配置项类型默认值说明intervalnumber \| autoautoSharedValue 更新间隔毫秒传auto时按设备帧率选择间隔iosReferenceFrameIOSReferenceFrameAutoiOS 上使用的参考坐标系adjustToInterfaceOrientationbooleantrue是否根据当前屏幕方向校正测量值例如横屏时 x/y 轴需要交换/取反才能在屏幕上正确呈现默认值合并逻辑见 useAnimatedSensor.ts。另外Hook 会通过useRef对比新旧配置interval、iosReferenceFrame、adjustToInterfaceOrientation任一变化即视为配置变更并在配置变化后重新注册传感器。interval 的底层处理在 Sensor.ts 中interval会被透传给原生模块ReanimatedModule.registerSensor当值为auto时实际传入-1由原生层决定采样频率通常对齐设备帧率从而在流畅度与功耗之间取得平衡ReanimatedModule.registerSensor( sensorType, config.interval auto ? -1 : config.interval, config.iosReferenceFrame, eventHandler );iosReferenceFrame 详解IOSReferenceFrame枚举见 commonTypes.ts对齐 Apple Core Motion 的CMAttitudeReferenceFrame定义仅对 iOS 生效值含义XArbitraryZVertical任意 X 轴、Z 轴垂直不校正磁偏角XArbitraryCorrectedZVertical任意 X 轴已做磁偏角校正、Z 轴垂直XMagneticNorthZVerticalX 轴指向磁北、Z 轴垂直XTrueNorthZVerticalX 轴指向真北、Z 轴垂直Auto自动选择无磁力计的设备如 iPod用XArbitraryZVertical有磁力计的设备用XArbitraryCorrectedZVertical四、返回值 AnimatedSensor 详解useAnimatedSensor返回一个AnimatedSensor对象类型见 commonTypes.ts包含四个属性{ sensor: SharedValueValue3D | ValueRotation | null, // 传感器实时读数 unregister: () void, // 停止监听传感器更新 isAvailable: boolean, // 设备上传感器是否可用 config: UserConfig, // 用户提供的配置 }数据结构的初始值与更新Sensor类在初始化时会通过makeMutable创建 SharedValue初始值取决于传感器类型见 Sensor.tsROTATION 传感器初始化为全 0 的RotationVector{ qw: 0, qx: 0, qy: 0, qz: 0, yaw: 0, pitch: 0, roll: 0, interfaceOrientation: 0 }其余传感器初始化为全 0 的Value3D{ x: 0, y: 0, z: 0, interfaceOrientation: 0 }。之后每当原生传感器产生新数据就会触发注册的回调 worklet把最新测量值写回sensorData.value见 useAnimatedSensor.ts从而自动驱动依赖它的动画 worklet。三个数据类型的结构3DVectorcommonTypes.ts{ x: number; // X 轴分量 y: number; // Y 轴分量 z: number; // Z 轴分量 interfaceOrientation: InterfaceOrientation; // 当前设备方向 }RotationVectorcommonTypes.ts{ qw: number; // 四元数标量分量 qx: number; // 四元数向量分量 qy: number; qz: number; yaw: number; // 偏航角弧度 pitch: number; // 俯仰角弧度 roll: number; // 侧倾角弧度 interfaceOrientation: InterfaceOrientation; // 当前设备方向 }InterfaceOrientation枚举commonTypes.ts用于标记测量时的设备方向Android 与 iOS 的对应关系如下值AndroidiOSROTATION_0默认方向竖屏portraitROTATION_90旋转 90°横屏右向landscapeHome 键在右侧ROTATION_180旋转 180°倒置upside downROTATION_270旋转 270°横屏左向landscapeHome 键在左侧五、接口方向自动校正的原理adjustToInterfaceOrientation: true默认时测量值会在写入 SharedValue 之前按当前interfaceOrientation进行坐标系变换。以测试用例 sensors.test.ts 中验证的行为为例3D 向量adjustVectorToInterfaceOrientation见 useAnimatedSensor.tsROTATION_90x -y, y xx 轴与 y 轴交换并取反ROTATION_270x y, y -xROTATION_180x、y同时取反ROTATION_0不做变换。旋转矢量adjustRotationToInterfaceOrientation见 useAnimatedSensor.ts对pitch/roll/yaw做对应旋转变换后再通过eulerToQuaternion重新计算四元数保证欧拉角与四元数始终自洽。该行为在 sensors.test.ts 中针对ROTATION_0 / 90 / 180 / 270四种方向都有精确断言例如 3D 传感器在 90° 横屏下x: 1, y: 2会被校正为x: -2, y: 1。六、完整示例用旋转传感器驱动视图缩放下面是一个可直接运行的完整示例它监听ROTATION传感器并根据设备的 yaw水平朝向与 pitch俯仰动态改变黑色色块的高度和宽度import Animated, { useAnimatedSensor, useAnimatedStyle, SensorType, withTiming, } from react-native-reanimated; function UseAnimatedSensorExample() { const animatedSensor useAnimatedSensor(SensorType.ROTATION, { interval: 10, // 每 10ms 更新一次读数 }); // - 初始化 const style useAnimatedStyle(() { const yaw Math.abs(animatedSensor.sensor.value.yaw); const pitch Math.abs(animatedSensor.sensor.value.pitch); return { height: withTiming(yaw * 200 20, { duration: 100 }), // - 用法 width: withTiming(pitch * 200 20, { duration: 100 }), // - 用法 }; }); return ( View style{{ flex: 1, justifyContent: center, alignItems: center }} Animated.View style{[{ backgroundColor: black }, style]} / /View ); }关键点说明读取位置animatedSensor.sensor.value必须在 worklet如useAnimatedStyle的回调内部读取才能保证动画在 UI 线程上运行、不产生主线程卡顿可选平滑如示例所示可以把原始读数包一层withTiming/withSpring避免传感器高频抖动导致的样式突变传感器不可用返回的isAvailable标志可用于判断设备是否支持所选传感器例如模拟器或缺少磁力计的低端设备上ROTATION可能不可用此时应提供降级 UI。七、传感器可用性、注销与多实例共享可用性判断与注册失败registerSensor返回-1表示传感器不可用见 useAnimatedSensor.ts此时isAvailable为falseunregister为 no-opSharedValue 保持初始全 0 值。在 Web 端JS 侧还会打印告警日志提示传感器不可用、需要 HTTPS 安全上下文https:或 iOS Safari 需要额外授权见 JSReanimated.ts。多实例共享SensorContainer 的复用机制SensorContainer见 SensorContainer.ts按sensorType * 100 iosReferenceFrame * 10 adjustToInterfaceOrientation生成传感器 ID用于缓存和复用原生传感器实例。这意味着同一传感器配置被多个组件使用时底层只会注册一个原生传感器通过引用计数listenersNumber管理最后一个监听者注销后才真正关闭原生传感器见 SensorContainer.ts。生命周期管理在组件卸载时useEffect的清理函数会自动调用unregister见 useAnimatedSensor.ts开发者一般无需手动调用但在特定场景如传感器变化后想提前停止监听可以主动调用返回的unregister函数。八、测试验证orientation 校正的行为基准仓库中的 sensors.test.ts 是理解传感器行为的最佳活文档它用testing-library/react-hooks的renderHook渲染 Hook、mock 掉core层的registerSensor然后直接向事件回调注入模拟数据验证四类行为ROTATION 传感器原样透传L60-L81adjustToInterfaceOrientation: false时数据不做任何变换3D 传感器原样透传L83-L100旋转传感器四种方向校正L102-L187覆盖ROTATION_0/90/180/270并验证了校正后的四元数与欧拉角含符号变化3D 传感器四种方向校正L189-L253验证 x/y 轴交换与取反规则。此外测试中还保留了旋转转换计算器的注释引用方便你在调整自定义旋转逻辑时核对数值。九、注意事项与平台差异:::caution iOS 位置服务要求 在 iOS 上若要读取传感器数据需要先在设备上开启位置服务设置 隐私 位置服务Settings Privacy Location Services。 :::其余需要留意的平台差异Web 端基于 W3C 通用传感器 APIAccelerometer、Gyroscope等实现要求页面处于安全上下文HTTPSiOS Safari 还要求额外的传感器权限授权见 JSReanimated.ts测试环境 / Jest mock仓库在 mock.ts 中为useAnimatedSensor提供了 mock 实现返回全 0 的传感器数据与 no-op 的unregister方便在单元测试中稳定渲染组件interval: auto按设备帧率采样动画流畅度与电量消耗的均衡选择需要更高采样率时显式传入毫秒数如示例中的10。十、总结useAnimatedSensor把设备传感器与 Reanimated 的 UI 线程动画体系无缝衔接5 种传感器加速度计、陀螺仪、重力、磁场、旋转矢量通过SensorType枚举一键切换interval、iosReferenceFrame、adjustToInterfaceOrientation三个配置项分别控制采样频率、iOS 参考坐标系与方向自动校正返回值AnimatedSensor.sensor是 SharedValue可在任意 worklet 中直接读取配合useAnimatedStyle即可实现如设备倾斜驱动元素形变/位移/透明度的沉浸式交互底层由SensorContainer统一管理原生传感器实例的注册、复用与引用计数释放Hook 卸载时自动清理。文中涉及的源码与测试均可直接在当前仓库中继续研读Hook 实现、类型定义、原生桥接封装、实例管理、行为测试 以及 Web 实现。【免费下载链接】react-native-reanimatedReact Natives Animated library reimplemented项目地址: https://gitcode.com/GitHub_Trending/re/react-native-reanimated创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表