React Native Animations, L oop анимация без сброса анимированного значения после итерации - PullRequest
0 голосов
/ 20 июня 2020

React-Native Animated: как l oop анимацию без сброса значения анимации после каждого l oop.

Я изо всех сил пытался выяснить метод зацикливания React Native Animations без сброса анимированное значение возвращается к его исходному значению.

Например, я сделал простую анимацию «Sway», которая перемещала бы мой компонент влево и вправо

  let animationX = new Animated.Value(0);

  const left = (toValue) => Animated.timing(animationX, {toValue: -toValue, duration: 1500})
  const right = (toValue) => Animated.timing(animationX, {toValue, duration: 1500})

  const startSwayAnimation = () => {
    Animated.loop(
      Animated.sequence([
        left(100),
        right(100),
      ])
    ).start()
  }

Проблема заключалась в том, что моя переменная animationX сбрасывалась обратно до 0 после каждого l oop. Мне не удалось найти никаких полезных ресурсов о том, как l oop анимацию без сброса значения, хотя на github есть две мертвые проблемы:

https://github.com/facebook/react-native/issues/18028 https://github.com/facebook/react-native/issues/20560

Я был почти готов рассмотреть вопрос о SO, но затем я попытался создать рекурсивную функцию для l oop анимации, и она отлично сработала

В Если кто-то еще борется с этим или знает лучшее решение (возможно, какая-то конфигурация для Animated.l oop, о которой я не знаю), я решил поделиться этим на SO.

Ответы [ 2 ]

1 голос
/ 21 июня 2020

Исправление утечки памяти для вышеуказанного ответа !!

Моя предыдущая реализация привела к утечке памяти. Я также выяснил, как сделать ее многоразовой в пользовательском хуке!

const useLoopAnimation = (animationFn) => {
  // loopAnimation halts when changing state variables (using useState) for unknown reason
  // so use a let variable instead.
  let stopped = false;
  const loopAnimation = () => {
    if (stopped) return false;
    animationFn().start(() => loopAnimation());
  };

  // this runs on component dismount to stop the recursive loop.
  useEffect(() => () => {
    stopped = true;
  });
  return loopAnimation;
};

а затем в вашем компоненте вы используете его так

  const loopAnimation = useLoopAnimation(() =>
    Animated.sequence([left(100), right(100)])
  );
0 голосов
/ 20 июня 2020

Вы можете использовать рекурсию для вызова одной и той же анимации снова и снова, вызывая одну и ту же функцию в обратном вызове запуска.

  let animationX = new Animated.Value(0);
  const left = (toValue: number) =>
    Animated.timing(animationX, { toValue: -toValue, duration: 1500 });
  const right = (toValue: number) =>
    Animated.timing(animationX, { toValue, duration: 1500 });

    const loopSway = () => {
        Animated.sequence([
          left(100),
          right(100),
        ]).start(() => loopSway())
    }

Однако мне не удалось создать повторно используемую функцию loopAnimation. при попытке я получаю сообщение об ошибке undefined is not an object (evaluating 'animations[current].start')

    const sway = Animated.sequence([
      left(100),
      right(100),
    ])

    const loopAnimation = (animation) => {
        animation.start(() => loopAnimation(animation))
    }

    const loopSway = loopAnimation(sway)

Похоже, что в React Native Animated есть побочный эффект, который не позволяет назначать анимации как константы: (

Я пробовал клонирование анимации

    const loopAnimation = (animation) => {
        const animationClone = {...animation}
        animation.start(() => loopAnimation(animationClone))
    }

, и я попытался сделать анимацию значением состояния.

Но не добился успеха ни с одним, поэтому был бы признателен, если бы кто-нибудь знал, как сделать это fn многоразовый!

...