react-native - 动画从 360 度旋转到 0 度 - iOS 传感器

标签 react-native animation css-animations

当我尝试对映射到 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) 来存储航向的当前值。
接下来我们计算两个距离:
  • 第一个 - 基本距离 - 是当前传感器值和我们当前航向值之间的循环距离。
  • 第二个用于解决“趋势”,例如询问“如果我们将航向增加 1(步),循环距离会增加还是减少?”
  • const baseDistance = 循环距离(
    传感器航向,
    我的标题引用
    );
    常量趋势 =
    循环距离(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/

    相关文章:

    css - 如何为图案填充添加背景颜色?

    reactjs - react native : How to stop map markers from re-rendering on every state update

    reactjs - 无法使用useRef钩子(Hook)访问React Native中的scrollToIndex()方法

    react-native - 使用 navigation.goBack() 时如何将数据发送回前一屏幕?

    math - 一些数学和动画

    javascript - 我可以为 CSS 背景图像设置不透明度动画吗?

    react-native TouchableHighlight 禁用 onPress 颜色闪烁

    ios - UIView 页面 curl 动画不适用于 block

    css - 为什么动画元素会破坏关联伪元素的堆叠上下文?

    javascript - 动画之间有延迟的 CSS Newsticker(和其他问题)