2017-02-10 4 views
5

У меня есть простая анимация в захвате петли моего компонента, как это:Как остановить анимацию цикла в React Native?

runAnimation() { 
    console.log('run animation'); 
    this.state.angle.setValue(0); 
    Animated.timing(this.state.angle, { 
     toValue: 360, 
     duration: 8000, 
     easing: Easing.linear 
    }).start(() => this.runAnimation()); 
} 

... 

<Animated.Image 
    style={[ 
     styles.rotate, 
     { transform: [ 
      { rotate: this.state.angle.interpolate({ 
       inputRange: [0, 360], 
       outputRange: ['0deg', '360deg'] 
      })}, 
     ]} 
    ]} 
    source={require('./spinning_ball.png')} 
/> 

Как бы остановить эту анимацию? Например, при переходе на другой экран или после нажатия пользователем кнопки.

Я попытался с помощью this.state.angle.stopAnimation() но заметил запустить анимацию еще напечатанный в консоли. Есть ли другой метод остановки, который я должен вызывать, чтобы предотвратить запуск обратного вызова?

ответ

7

Основываясь на моем комментарии в ответе Нгуена Хоанга. Вот еще один способ, чтобы остановить циклическую анимацию, если вы звоните this.state.angle.stopAnimation():

runAnimation() { 
    this.state.angle.setValue(0); 
    Animated.timing(this.state.angle, { 
    toValue: 360, 
    duration: 8000, 
    easing: Easing.linear 
    }).start((o) => { 
    if(o.finished) { 
     this.runAnimation(); 
    } 
    }); 
} 
+0

Оба решения работали, но это казалось намного более чистой реализацией. –

+0

Хороший улов o.finished –

3

Вы можете создать переменную stopAnimation, чтобы остановить анимацию, когда захотите, только когда stopAnimation === false, а затем обратный вызов runAnimation. Как пример:

this.state = { stopAnimation: false } 

runAnimation() { 
    this.state.spinValue.setValue(0); 
    Animated.timing(
    this.state.spinValue, 
    { 
     toValue: 1, 
     duration: 3000, 
     easing: Easing.linear 
    } 
).start(() => { 
    if(this.state.stopAnimation === false) { 
     this.runAnimation(); 
    } 
    }); 
} 

Так что вам просто нужно создать кнопку, которая вызывать функцию this.state = { stopAnimation: true }, чтобы остановить анимацию.

Пример: https://rnplay.org/apps/Lpmh8A.

+0

Это единственный способ сделать это? Я уже рассматривал это как возможность, но это не похоже на самый чистый подход. Мне также интересно, может ли кто-нибудь объяснить, почему stopAnimation() запускает обратный вызов, когда анимация технически не заканчивается. Или это? Кажется, не имеет смысла для меня. –

+0

где находится место u call 'this.state.angle.stopAnimation()' @MichaelCheng –

+0

@MichaelCheng Обратный вызов в 'start()' будет вызываться независимо. Если он завершится нормально, в обратном вызове вы получите объект '{finished: true}'. Но если он прерывается (например, 'stopAnimation()'), вы получите '{finished: false}' вместо этого в обратном вызове. –

0

Установить глобальную переменную

let dataloaded = false; 

Чтобы остановить анимацию переопределить переменную (DataLoaded) всякий раз, когда вы хотите

componentWillUnmount() { 
    dataloaded = true; 
} 

onPress={() => { 
    dataloaded = true; 
}} 

Окончательный код будет выглядеть так:

runAnimation() { 
    console.log('run animation'); 
    this.state.angle.setValue(0); 
    Animated.timing(this.state.angle, { 
     toValue: 360, 
     duration: 8000, 
     easing: Easing.linear 
    }) 
    .start(() => { 
     if (! dataloaded) { 
      this.runAnimation(); 
     } 
    }) 
} 
Смежные вопросы