尝试对 React Native 文本值进行动画处理

问题描述 投票:0回答:3

所以基本上我试图让这个渲染函数实际实时更新值(到目前为止,它只是在动画完成后跳转到最终值)

this.state = {
  pleaseDisplayMe: Animated.value(0);
}

triggerAnimation(){
  Animated.timing(
        this.state.pleaseDisplayMe,
        {toValue: 100,
        duration: 5000}
      ).start();
}

render(){
  return  <Animated.Text>{this.state.pleaseDisplayMe}</Animated.Text>
}

我觉得因为这个库可以在底层对值进行动画处理,所以必须有一种方法来显示正在发生的事情。或者我可以通过样式输入某种内容/值属性吗?

我已经尝试自定义编写自己的 setInterval 函数,但我需要它与其他动画的计时更好地保持一致,并且我很想访问 RN 的 Easing 库!

谢谢!

reactjs react-native react-animated
3个回答
5
投票

React Native 有计时器可供您使用。例如,要使用 setInterval 完成您想要完成的任务:

state = {pleaseDisplayMe: 0}

componentDidMount() {
  setInterval(() => {
    this.setState({pleaseDisplayMe: this.state.pleaseDisplayMe + 1})
  }, 1000);
}

render() {
  return (
    <Text>{this.state.pleaseDisplayMe}</Text>
  )
}

但是,如果您尝试实际从动画中获取值,则应该将侦听器附加到 Animated 并从那里获取值,因为无法同步读取该值,因为它可能是本机驱动的 。一个可能非常糟糕的例子(我也是 React Native 的新手)是这样的:

state = {
  pleaseDisplayMe: new Animated.Value(0),
  value: 0,
}

triggerAnimation(){
  this.state.pleaseDisplayMe.addListener(({value}) => this.setState({value: value}));
  Animated.timing(
    this.state.pleaseDisplayMe,
    {toValue: 100,
    duration: 5000}
  ).start();
}

render() {
  return (
    <Text>{this.state.value}</Text>
  )
}

2
投票

我使用这个库(https://github.com/wkh237/react-native-animate-number)来实现这种效果。

import AnimateNumber from '../AnimateNumber';

const targetNumber = 1000;

<AnimateNumber
  value={targetNumber}
  interval={26} // in miliseconds
  formatter={(number) => parseInt(number)}
  easing={'easeOut'}
/>

格式化程序对我来说很重要,否则它会使用很长的小数进行动画处理(例如,从 0 到 1000,您会看到 33.3280329804,但使用格式化程序您只能看到整数)。

另外,查看lib源代码,我意识到起始编号是硬编码的(它总是从0开始)。由于它是一个非常简单的库(只有一个文件),因此您可以轻松复制 dist/index.js 并将其粘贴到您的项目中并覆盖您需要的代码。

就我而言,我希望组件在安装时不动画,但仅在 value 属性更改时才动画,因此我更改了它的构造函数内部:

    this.state = {
      value : 0,
      displayValue : 0
    }

对此:

this.state = {
      value : props.value,
      displayValue : props.value,
    }

0
投票

我制作了一个文本封面组件,可以显示任何数字并为其更改设置动画。这很简单。

function LiveNumber({style, value}) {
    value = parseInt(value) || 0;
    const [s] = useState({ saved: 0, step: 1 }); // State hack instead of useRef for easier reading
    const [current, setValue] = useState(0);
    
    const timeout = 150; // animation time, ms
    const interval = 10; // frame time, ms

    // props changed
    if (s.saved != value) {
        s.saved = value;
        s.step = (value - current) / timeout * interval;
        Math.abs(s.step) < 1 && (s.step = s.step < 0 ? -1 : 1);
    }

    // animation
    if (current != s.saved) {
        if (Math.abs(s.saved - current) < Math.abs(s.step)) {
            setValue(s.saved);
        } else {
            setTimeout(() => {
                setValue(Math.round(current + s.step));
            }, interval);
        }
    }

    return <Text style={style}>{current}</Text>
}

更换即可

<Text style={styles.counterText}>{counter}</Text>

<LiveNumber style={styles.counterText} value={counter} />

您可以修改

timeout
interval
常量来配置动画。

© www.soinside.com 2019 - 2024. All rights reserved.