0

我正在尝试为恐慌症患者制作一个呼吸应用程序以循环扩大和缩小一个圆圈。我正在尝试使文本随动画及时更改。呼吸状态是圆圈中显示的文本变量 - 它可以是“吸入”、“保持”或“呼出”。动画使圆圈在breathTimings.in 的持续时间内从60% 变为全尺寸,然后它应该变为说“hold”,然后暂停breathTimings.hold,然后在说“exhale”的同时缩小回60%。

class BreatheCircle extends React.Component {
  state = {
    animated:new Animated.Value(0.6),
    breathe: 'Inhale',

  }

  componentDidMount(){
    this.state.animated.setValue(0.6)
    this.animateCircle();
  }
  componentWillUnmount(){
    Animated.timing(this.state.animated).stop();
  }
  sleep(milliseconds) {
    var start = new Date().getTime();
    for (var i = 0; i < 1e7; i++) {
      if ((new Date().getTime() - start) > milliseconds){
        break;
      }
    }
  }
  animateCircle(){
      this.setState({breathe: 'Inhale'})
      Animated.timing(this.state.animated, {toValue: 1, duration:breatheTimings.in*1000}).start()
      this.sleep(breatheTimings.in*1000)
      this.setState({breathe: 'Hold'})
      this.sleep(breatheTimings.hold*1000)
      this.setState({breathe: 'Exhale'})
      Animated.timing(this.state.animated, {toValue: 0.6, duration:breatheTimings.out*1000}).start()
      this.sleep(breatheTimings.out*1000)
      this.animateCircle()
      }

目前这不起作用(用expo测试它)请有人给我关于去哪里的建议。谢谢

4

2 回答 2

0

您在调用setState的同时,JavaScript 不会停止并等待其他函数完成。

我不会重写这段代码,并进入你的问题的逻辑,但一种正确的方法可能是使用prevState,也许在 sleep 函数中。例如:

sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if (!(new Date().getTime() - start) > milliseconds){
      this.setState(prevState => {
        if (prevState.breathe === "Inhale") {
          prevState.breathe = "hold";
        } else if(prevState.breathe === "hold") {
          prevState.breathe = "Exhale";
        } else {
          prevState.breathe = "Inhale"
        }
        return prevState
      });
    }
  }
}

来自React 文档

这种形式的 setState() 也是异步的,同一周期内的多次调用可能会被批处理在一起。

...

将 setState() 视为更新组件的请求而不是立即命令。为了更好地感知性能,React 可能会延迟它,然后一次更新多个组件。React 不保证立即应用状态更改。

于 2018-10-08T08:48:59.850 回答
0

你不需要睡眠功能,你可以尝试一个 Animated.sequence (写作时文档在这里)。我建议你写下“Inhale”、“Exhale”和“Hold”,并使用不透明度进行游戏。

class BreatheCircle extends React.Component {
      state = {
          circleAnimation: new Animated.Value(0.6),
          holdAnimation: new Animated.Value(0),
          inhaleAnimation: new Animated.Value(0),
          exhaleAnimation: new Animated.Value(0),
      }

  breathAnimation = Animated.sequence([
      Animated.timing(this.state.inhaleAnimation, {toValue: 1, duration:100}),
      Animated.timing(this.state.circleAnimation, {toValue: 1, duration:breatheTimings.in*1000}),
      Animated.timing(this.state.inhaleAnimation, {toValue: 0, duration:100}),
      Animated.timing(this.state.holdAnimation, {toValue: 1, duration:100}),
      Animated.timing(this.state.holdAnimation, {toValue: 0, duration:100, , delay: breatheTimings.hold*1000}), //delay for the hold to disappear
      Animated.timing(this.state.exhaleAnimation, {toValue: 1, duration:100}),
      Animated.timing(this.state.circleAnimation, {toValue: 0.6, duration:breatheTimings.out*1000}),
      Animated.timing(this.state.exhaleAnimation, {toValue: 0, duration:100}),
  ])

  componentDidMount(){
    // this.state.animated.setValue(0.6) // state already declare
    this.animateCircle();
  }
  componentWillUnmount(){
    this.breathAnimation.stop();
  }

  animateCircle(){
      this.breathAnimation.start(() => this.animatedCircle())
  }


  //[...]

  <Text style={{opacity: this.holdAnimation}}>Hold<Text>
  <Text style={{opacity: this.inhaleAnimation}}>Inhale<Text>
  <Text style={{opacity: this.exhaleAnimation}}>Exhale<Text>
于 2018-10-08T09:18:27.213 回答