当我尝试对映射到 iOS 指南针的旋转进行动画处理时,动画会在相反的方向上旋转一整圈。
对于 CSS3 转换,有一个关于此的相关问题,建议我应该继续增加超过 360 度的度数,它就会环绕。好吧,这种技术不能与传感器数据一起使用,因为它只是从 359、360、直接到 0。而 React Native 中的插值算法只是不处理这个。
这是我当前的代码:
const degrees = useRef(new Animated.Value(0)).current;
useEffect(() => {
Animated.timing(
degrees,
{
toValue: location.trueHeading,
useNativeDriver: true
}
).start();
}, [location.trueHeading])
const renderArrow = () => {
return (
<Animated.View
style={{
transform: [{
rotate: ((degrees.interpolate({
inputRange: [0, 360],
outputRange: ['0deg', '-360deg']
})))
}]
}}
>
<IconArrow />
</Animated.View>
)
}
我不需要 React Native 的具体答案。一般回答你将如何解决这个问题就足够了。谢谢
最佳答案
所以我在一段时间后回答我自己的问题来解释我是如何解决这个问题的。
该解决方案不使用 React 的 Animation 框架(也不使用 nativeDriver),而是使用 useAnimationFrame 回调。所以我们不会触及插值方法的问题。
相反,我选择计算向左旋转和向右旋转“步”量之间到所需航向(从传感器)的距离。它被称为循环距离,它的实现是这样的:
function cyclicDistance(current: number, now: number): number {
const abs = Math.abs(current - now);
const distanceAround = 360 - abs;
const distanceStraight = abs;
const distance = Math.min(distanceAround, distanceStraight);
return distance;
}
因此,我们通过 Math.min 获得了两种可能解决方案的最短路径。我正在使用 Reference (useRef Hook) 来存储航向的当前值。
接下来我们计算两个距离:
传感器航向,
我的标题引用
);
常量趋势 =
循环距离(sensorHeading + 1, myHeadingRef) < baseDistance
? 1
:-1;
最后一块拼图是值(value)环绕。我们允许度数的值高于 360 或低于 0。React 的 CSS 旋转变换可以处理这个问题,因此我们可以利用它。
if (myHeading.current < 0) {
myHeading.current += 360;
} else if (myHeading.current > 360) {
myHeading.current -= 360;
}
把它们放在一起:function cyclicDistance(current: number, now: number): number {
const abs = Math.abs(current - now);
const distanceAround = 360 - abs;
const distanceStraight = abs;
const distance = Math.min(distanceAround, distanceStraight);
return distance;
}
const [heading, setHeading] = useState(0);
const myHeading = useRef<number>(0);
const locationRef = useRef<Array<number>>([0, 0]);
const step = () => {
if (myHeading.current < 0) {
myHeading.current += 360;
} else if (myHeading.current > 360) {
myHeading.current -= 360;
}
const maxDistance = 10;
const distance = cyclicDistance(
myHeading.current,
locationRef.current[1]
);
const tendency =
cyclicDistance(myHeading.current + 1, locationRef.current[1]) <
distance
? 1
: -1;
const move = distance > maxDistance ? maxDistance : distance;
const newpos = myHeading.current + tendency * move;
myHeading.current = newpos;
setHeading(myHeading.current);
};
useAnimationFrame(() => step(), []);
它可能需要一点重构来提高可读性,但它足以让您了解这个想法。
关于react-native - 动画从 360 度旋转到 0 度 - iOS 传感器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65622200/