我的 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;
}