首页 > 解决方案 > 反应计时器没有正确转换

问题描述

我的 React Timer 几乎准备好了,我给它添加了一个动画,但是有一些问题:首先,当你从会话中中断计时器时,它会闪烁 2 或 3 秒/渲染(它首先显示 -01:60在它上面然后环形动画需要时间来“重新填充”),我如何防止奇怪的渲染和环形的重新填充?它有一个过渡属性,我当时尝试将其设置为无或将持续时间设置为零,因此它不需要时间,但它似乎没有任何效果。

其次,当您暂停并播放计时器很多时,显示的秒数会减少 3,而它们应该停在那里,而且如果我能够解决这个问题,那么当我暂停并播放计时器很多时,戒指不会与计时器同步(因为转换发生在一秒的开始,所以即使您在该秒的中途暂停计时器,转换也不会停止)

定时器组件:

import * as React from "https://cdn.skypack.dev/react@17.0.1";
import * as ReactDOM from "https://cdn.skypack.dev/react-dom@17.0.1";
var timer_is_paused = true, timer_is_resetted = true;
class Timer extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      mStr: this.props.s_mins < 10 ? "0" + this.props.s_mins.toString() : 
      this.props.s_mins.toString(),
      sStr: "00",
      onBreak: false,
      class: "fas fa-play",
      strke: "rgb(12, 140, 214)",
      strke_len: 942,
      tr: "stroke-dasharray 0.3s linear;"
    }
    this.expected;
    this.interval = 300;
    this.currMins = this.props.s_mins - 1; //25:00 => 24:60
    this.circleDecrement = 942 / this.props.s_mins / 60;
    this.strkeLen = 942;
    this.start_timer = this.start_timer.bind(this);
    this.play_pause = this.play_pause.bind(this);
    this.reset = this.reset.bind(this);
  }
  start_timer() {
    if(timer_is_paused) return false;
    this.strkeLen -= this.circleDecrement;
    var dt = Date.now() - this.expected;
    var seconds = Math.floor(dt / this.interval), 
        minutes = Math.floor(seconds / 60);
    if(seconds === (this.currMins + 1) * 60 + 1) {
      this.setState({tr: "none !important;"})
      this.setState(state => ({
        mStr: "00",
        sStr: "00",
        strke_len: 0,
        onBreak: !state.onBreak,
        tr: "stroke-dasharray 0.3s linear;"
      }));
      this.currMins = (this.state.onBreak ? this.props.b_mins : this.props.s_mins) - 1;
      this.circleDecrement = 942 / 60 / (this.state.onBreak ? this.props.b_mins : this.props.s_mins);
      this.strkeLen = 942;
      this.expected = Date.now();
    }
    else {
    seconds = (60 * (minutes + 1) - seconds).toString(); //same as (60 - seconds % 60).toString();
    minutes = (this.currMins - minutes).toString();
    console.log(minutes, seconds);
     this.setState({
      mStr: minutes < 10 ? "0" + minutes : minutes,
      sStr: seconds < 10 ? "0" + seconds : seconds,
      strke_len: Math.floor(this.strkeLen)
    });
    }
    setTimeout(this.start_timer, this.interval - dt % this.interval);
  }
  play_pause() {
    if (timer_is_paused) {
      this.setState({ class: "fas fa-pause"});
      timer_is_paused = false;
      if(timer_is_resetted) {
        this.expected = Date.now();
        timer_is_resetted = false;
      }
      setTimeout(this.start_timer, this.interval);
    }
    else {
      this.setState({class: "fas fa-play"});
      timer_is_paused = true;
    }
  }
  reset() {
    this.setState({
      mStr: this.props.s_mins < 10 ? "0" + this.props.s_mins.toString() : 
      this.props.s_mins.toString(),
      sStr: "00",
      onBreak: false,
      class: "fas fa-play",
      strke: "rgb(12, 140, 214)",
      strke_len: 942
    });
    this.currMins = this.props.s_mins - 1;
    this.circleDecrement = 942 / this.props.s_mins / 60;
    timer_is_paused = true;
    timer_is_resetted = true;
  }
    componentDidUpdate(prevProps) {
      if(this.props.s_mins !== prevProps.s_mins && !this.state.onBreak) {
        this.setState({
          mStr: this.props.s_mins < 10 ? "0" + this.props.s_mins.toString() :
          this.props.s_mins.toString(),
          sStr: "00"
        });
        this.circleDecrement = 942 / 60 / this.props.s_mins;
        this.currMins = this.props.s_mins - 1;
      }
      else if(this.props.b_mins !== prevProps.b_mins && this.state.onBreak) {
        this.setState({
            mStr: this.props.b_mins < 10 ? "0" + this.props.b_mins.toString() : 
            this.props.b_mins.toString(),
          sStr: "00"
        });
        this.currMins = this.props.b_mins - 1;
        this.circleDecrement = 942 / 60 / this.props.b_mins;
      }
    }
    render() {
      return <div><svg>
  <circle stroke= "grey" />
     <circle id="path" stroke={this.state.strke} transition={this.state.tr}
       stroke-dasharray={this.state.strke_len.toString() + " 942"}/>
        </svg>
        <div id="timeriii">
          <span id="timer-label">{this.state.onBreak ? "Break" : "Session"}</span><br />
          <span id="time-left">{this.state.mStr}:{this.state.sStr}</span><br />
            <button id="start_stop" onClick={this.play_pause} class="left-positioned">
                <i class={this.state.class}></i>
              </button>
          <button id="reset" onClick={this.reset} class="right-positioned"><i class="fas fa-undo" /></button>
</div>
        </div>
    }
}

圆的CSS:

#path {
  transform: rotate(90deg);
  transform-origin: center;
  transition: stroke-dasharray 0.3s linear;
  stroke-linecap: round;
}

笔链接:https ://codepen.io/harel_avv/pen/RwGQEXy

标签: cssreactjstimer

解决方案


推荐阅读