在 react-native-reanimated 中继续循环动画

Keep looping an animation in react-native-reanimated

我对 react-native 中的动画完全陌生,我正在尝试使用 react-native-reanimated 库创建动画脉动按钮。

动画概念对我来说还不是很清楚,但是通过修改别人的代码,我已经非常接近我想要创建的东西了。

我想让这个脉动的动画连续不断。目前,它脉动然后停止。我会很感激一些帮助。我包括了代码和点心,供您查看 运行 示例。请记住,我只是修改了别人的代码,所以我确信这段代码中有些东西是不必要的。我在使用此按钮时正在学习。

这里有 link 点心:https://snack.expo.io/@imsam67/reanimated-test

这是代码:

import React, { Component } from 'react';
import { StyleSheet, View } from 'react-native';

import Animated from 'react-native-reanimated';

const {
  divide,
  set,
  cond,
  startClock,
  stopClock,
  clockRunning,
  block,
  spring,
  debug,
  Value,
  Clock,
} = Animated;

function runSpring(clock, value, dest) {
  const state = {
    finished: new Value(0),
    velocity: new Value(0),
    position: new Value(0),
    time: new Value(0),
  };

  const config = {
    toValue: new Value(0),
    damping: 10,
    mass: 5,
    stiffness: 101.6,
    overshootClamping: false,
    restSpeedThreshold: 0.001,
    restDisplacementThreshold: 0.001,
  };

  return block([
    cond(clockRunning(clock), 0, [
      set(state.finished, 0),
      set(state.time, 0),
      set(state.position, value),
      set(state.velocity, -2500),
      set(config.toValue, dest),
      startClock(clock),
    ]),
    spring(clock, state, config),
    cond(state.finished, debug('stop clock', stopClock(clock))),
    state.position,
  ]);
}

export default class Example extends Component {
  constructor(props) {
    super(props);
    const clock = new Clock();
    this._trans = runSpring(clock, 10, 150);
  }

  componentDidMount() {}

  render() {
    return (
      <View style={styles.container}>
        <Animated.View
          style={[styles.circle, { borderWidth: divide(this._trans, 5) }]}>
        </Animated.View>
      </View>
    );
  }
}

const BOX_SIZE = 100;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'black',
  },
  circle: {
    backgroundColor: "white",
    borderColor: "red",
    borderRadius: 150,
    height: 150,
    width: 150
  }
});

使此动画循环的一种快速方法是将阻尼设置为 0。这将使 spring 动画无限期地播放。

const config = {
  toValue: new Value(0),
  damping: 0, // changed to 0
  mass: 5
  stiffness: 101.6,
  overshootClamping: false,
  restSpeedThreshold: 0.001,
  restDisplacementThreshold: 0.001,
};

但是您可能希望将 borderWidth 样式更改为除以更大的数字以防止边界半径过大。

<Animated.View
  style={[styles.circle, { borderWidth: divide(this._trans, 25) }]}>
</Animated.View>

您可以找到修改后的小吃here

对于像这样的重复动画,您还可以考虑使用 Lottie,它实现起来简单得多,但灵活性较差。

此外,您可以考虑使用 React Native Animations 中的 loop,它应该允许您设置边框半径。

另一种通过重新激活 1.x.x 来更好地控制它的方法是:

const [clock] = useState(() => new Clock());
const loopingValue = useMemo(() => {
const state = {
  finished: new Value(0),
  position: new Value(0),
  time: new Value(0),
  frameTime: new Value(0),
};

const config = {
  duration: new Value(2000),
  toValue: new Value(1),
  easing: Easing.linear,
};
const value = block([
  // start right away
  startClock(clock),

  // process your state
  timing(clock, state, config),

  // when over (processed by timing at the end)
  cond(state.finished, [
    // we stop
    stopClock(clock),

    // set flag ready to be restarted
    set(state.finished, 0),
    // same value as the initial defined in the state creation
    set(state.position, 0),

    // very important to reset this ones !!! as mentioned in the doc about timing is saying
    set(state.time, 0),
    set(state.frameTime, 0),

    // and we restart
    startClock(clock),
  ]),

  state.position,
]);
return interpolate(value, {
  inputRange: [0, 0.5, 1],
  outputRange: [0, 1, 0],
});
}, [clock]);

很多代码是从此处的 github 线程复制而来的:https://github.com/software-mansion/react-native-reanimated/issues/162