如何结合react-native-gesture-handler与Reanimated实现矩阵变换衰减效果?
问题:React Native新版Gestures API中结合矩阵变换与withDecay衰减效果
我正在学习react-native-gesture-handler和react-native-reanimated,想用矩阵实现变换,但不知道怎么结合withDecay这类物理动画函数。我要使用新版Gestures API,不想用旧版gestureHandler API。参考了一个通过矩阵相乘实现变换的示例,效果不错,但想加平移结束后的衰减滑动效果。尝试在.onEnd事件里实现,但代码跑不起来,我的尝试代码如下:
const pan = Gesture.Pan() .onChange(e => { matrix.value = multiply4( Matrix4.translate(e.changeX, e.changeY, 0), matrix.value, ); }) .onEnd(({velocityX, velocityY}) => { matrix.value = multiply4( Matrix4.translate( withDecay({velocity: velocityX}), withDecay({velocity: velocityY}), 0, ), matrix.value, ); });
解决方案
你代码失效的核心原因:withDecay返回的是动画驱动的动态值,而Matrix4.translate需要传入静态数值,直接混用会导致动画无法正确触发。以下提供两种可行的实现方式:
方式一:保留矩阵直接操作(适合复杂多变换场景)
通过监听衰减动画的每一帧增量,实时更新变换矩阵:
import { Gesture } from 'react-native-gesture-handler'; import { useSharedValue, withDecay, multiply4, Matrix4, runOnUI, useAnimatedReaction } from 'react-native-reanimated'; // 初始化变换矩阵 const matrix = useSharedValue(Matrix4.identity()); // 存储衰减过程中每帧的偏移增量 const tempDecayX = useSharedValue(0); const tempDecayY = useSharedValue(0); // 监听增量变化,更新矩阵 useAnimatedReaction( () => [tempDecayX.value, tempDecayY.value], ([dx, dy]) => { if (dx !== 0 || dy !== 0) { matrix.value = multiply4(Matrix4.translate(dx, dy, 0), matrix.value); // 重置增量,避免重复累加 tempDecayX.value = 0; tempDecayY.value = 0; } }, [matrix] ); const pan = Gesture.Pan() .onChange((e) => { // 手势拖动时直接更新矩阵 matrix.value = multiply4(Matrix4.translate(e.changeX, e.changeY, 0), matrix.value); }) .onEnd(({ velocityX, velocityY }) => { runOnUI(() => { // X轴衰减:计算每帧偏移增量并触发矩阵更新 tempDecayX.value = withDecay({ velocity: velocityX, onUpdate: (currentValue) => { tempDecayX.value = currentValue - tempDecayX.value; }, }); // Y轴衰减同理 tempDecayY.value = withDecay({ velocity: velocityY, onUpdate: (currentValue) => { tempDecayY.value = currentValue - tempDecayY.value; }, }); })(); });
方式二:拆分平移值(适合仅平移或简单变换场景)
将平移分量从矩阵中拆分出来,直接用withDecay驱动平移值,再组合成矩阵,代码更简洁:
import { Gesture } from 'react-native-gesture-handler'; import { useSharedValue, withDecay, Matrix4, useAnimatedStyle } from 'react-native-reanimated'; const translateX = useSharedValue(0); const translateY = useSharedValue(0); // 根据平移值生成变换矩阵 const animatedStyle = useAnimatedStyle(() => { const transformMatrix = Matrix4.translate(translateX.value, translateY.value, 0); // 如需叠加缩放、旋转等,可在此处组合多个矩阵 return { transform: [{ matrix: transformMatrix }] }; }); const pan = Gesture.Pan() .onChange((e) => { translateX.value += e.changeX; translateY.value += e.changeY; }) .onEnd(({ velocityX, velocityY }) => { // 直接用withDecay驱动平移值的衰减动画 translateX.value = withDecay({ velocity: velocityX }); translateY.value = withDecay({ velocity: velocityY }); });
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

