我正在 react native 中实现像 Instagram story 这样的功能,我需要在顶部实现一个进度条来指示当前故事的进度。目前,我有一个计时器,一旦故事开始播放,它就会开始计数:
onStart = (timeout: number, total: number) => {
const updateFrequncy = 1000 / PROGRESS_BAR_TICK;
this._timer = this.props.setInterval(() => {
this.setState(state => ({
progress:
state.progress +
(PROGRESS_BAR_SPEED * PROGRESS_BAR_RANGE * updateFrequncy) /
total,
}));
}, PROGRESS_BAR_TICK);
};
我正在将进度状态传递给进度条。(一个 Animated.View 组件,它将当前进度呈现为样式宽度(。所以基本上,由于 setState,它将每 PROGRESS_BAR_TICK 毫秒渲染一次。我面临的问题是 - 由于 JS 是单线程的,如果有另一个事件占用线程,或者 JS 线程在某些低端设备上很慢,进度条将变得垃圾。
有什么建议可以让它更流畅吗?
使用 setInterval,不如启动一个Animated.timing
动画来制作与故事相同的动画?如果用户暂停故事,您应该能够在动画上调用stop()
来停止它,然后以预期的剩余持续时间再次恢复它。
此外,与其对进度条的宽度进行动画处理,我鼓励在进度条上使用scaleX
或translateX
,进度条可以完全在本机线程上运行。
这是一个部分示例,缺少触发onStart
和onPause
的方法,因为我不确定组件的其余部分是什么样子的。
class Thing {
_progressValue = new Animated.Value(0);
onStart = (duration: number) => {
this._animation = Animated.timing(this._progressValue, {
duration: duration,
toValue: 100,
easing: Easing.linear,
useNativeDriver: true,
}).start();
};
onPause = () => {
if (this._animation != null) this._animation.stop();
};
render() {
return (
<View style={{width: 100, height: 5, backgroundColor: 'green'}}>
<Animated.View style={{width: 100, height: 5, backgroundColor: 'red', transform: [{translateX: this._progressValue}]}} />
</View>
);
}
}