React-animated 循环在短时间后变得非常有问题,React Native,Animated.Text

react-animated loop becomes very buggy after a short time, React Native, Animated.Text

我最近开始尝试在我试图用 React Native 制作的应用程序中使用动画。 我不是 100% 熟悉 React Animated,但我相信我尝试制作的动画非常简单。

我有一个屏幕,我希望一些文本从右侧滑入,暂停几秒钟,然后向左滑出,然后再与其他文本重复。

虽然我设法做到了这一点,但动画和文本很快变得非常有问题(也就是没有流畅的动画,一段时间后根本没有动画,文本会很快随机变化,等等)。

我不确定这是为什么,我尝试将 useNativeDriver 切换为 true 以希望获得更流畅的动画,但随后我收到一条错误消息,提示我无法使用样式 属性 'left'.

代码如下:

import React, { useState, useCallback, useEffect } from 'react';
import { Text, View, StyleSheet, Animated } from 'react-native';
import Constants from 'expo-constants';

function App() {
  let [wordsAnim] = useState(new Animated.Value(60)),
    runAnimation = () => {
      wordsAnim.setValue(60);
      Animated.sequence([
        Animated.timing(wordsAnim, {
          toValue: 0,
          duration: 1500,
          useNativeDriver: false,
        }),
        Animated.timing(wordsAnim, {
          toValue: -60,
          duration: 1500,
          delay: 3000,
          useNativeDriver: false,
        }),
      ]).start(({ finished }) => {
        runAnimation();
        updateWord();
      });
    };

  //An array of random words to display
  const words = ['First', 'Second', 'Third', 'Fourth'];

  //First word displayed is a random word from the array
  const [word, changeWord] = useState(
    words[Math.floor(Math.random() * words.length)]
  );

  //Update the word displayed with another random word from the array
  const updateWord = () => {
    const index = Math.floor(Math.random() * words.length);
    changeWord(words[index]);
  };

  useEffect(() => {
    runAnimation();
  });

  return (
    <View style={styles.container}>
      <Animated.Text
        style={{
          margin: 24,
          fontSize: 18,
          fontWeight: 'bold',
          textAlign: 'center',
          left: wordsAnim.interpolate({
            inputRange: [0, 100],
            outputRange: ['0%', '100%'],
          }),
        }}>
        {word}
      </Animated.Text>
    </View>
  );
}

export default App;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
});

你也可以找到这个例子here

我也会采纳有关动画或 React Native 的任何其他方面的任何技巧, 谢谢!!

正如@David784 所指出的,我的 runAnimation 在每次完成渲染后都会被重新触发。它应该只是 运行 在组件安装上。 添加一些回调就成功了!

下面的工作代码:

import React, { useState, useCallback, useEffect } from 'react';
import { Text, View, StyleSheet, Animated } from 'react-native';
import Constants from 'expo-constants';

function App() {
  let [wordsAnim] = useState(new Animated.Value(60)),
    runAnimation = useCallback(() => {
      wordsAnim.setValue(60);
      Animated.sequence([
        Animated.timing(wordsAnim, {
          toValue: 0,
          duration: 1500,
          useNativeDriver: false,
        }),
        Animated.timing(wordsAnim, {
          toValue: -60,
          duration: 1500,
          delay: 3000,
          useNativeDriver: false,
        }),
      ]).start(({ finished }) => {
        updateWord();
        runAnimation();
      });
    }, [updateWord, wordsAnim]);

  //An array of random words to display
  const words = ['First', 'Second', 'Third', 'Fourth'];

  //First word displayed is a random word from the array
  const [word, changeWord] = useState(
    words[Math.floor(Math.random() * words.length)]
  );

  //Update the word displayed with another random word from the array
  const updateWord = useCallback(() => {
    const index = Math.floor(Math.random() * words.length);
    changeWord(words[index]);
  }, [words]);

  useEffect(() => {
    runAnimation();
  }, [runAnimation]);

  return (
    <View style={styles.container}>
      <Animated.Text
        style={{
          margin: 24,
          fontSize: 18,
          fontWeight: 'bold',
          textAlign: 'center',
          left: wordsAnim.interpolate({
            inputRange: [0, 100],
            outputRange: ['0%', '100%'],
          }),
        }}>
        {word}
      </Animated.Text>
    </View>
  );
}

export default App;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
});