模拟先快后慢的加载进度

299 阅读2分钟

背景

在页面达到完全可用之前,向用户展示一个加载进度条可以有效缓解用户的等待焦虑。但一个真实反映页面中各个资源的加载进度的功能是相对复杂的。

一个成本较低的方法是制作一个假的进度条。或者说,制作一个「逼真的进度条」。

进度条的「逼真」在于符合我们日常的常识:加载速度先快后慢点击这里 查看线上演示。

本文将介绍我们制作一个「逼真的进度条」所使用的数学原理,并给出 React Hooks 的代码实现。

方案

首先,我们设计一下它的功能

  1. 进度百分数自动增长,范围从 0% 到 100%
  2. 增长的速度越来越慢,直到 99% 停住(没错,这就是为什么你们永远停在99%,是程序员故意的!)
  3. 当页面加载完成后,直接将进度条元素隐去即可。

我们使用下面的函数来模拟先快后慢的进度变化。

y=1eαxy=1-e^{-\alpha x}

它的函数图像如下:

desmos-graph.png

其中,

  • xx 为时间,范围从0到1。其中 x=0x=0 表示加载开始的时刻;x=1x=1 表示加载结束的时刻(此后进度无需再变化,对应上述的「停在99%」)
  • yy 为模拟的进度,范围从0到1,即:0% - 100% 。

问: α=?\alpha=? 答: 带入 x=1,y=0.99x=1, y=0.99, 易得 α5\alpha\approx5

useFadeProgressPercent

代码实现如下,点击这里查看线上演示。

/**
 * 模拟进度条百分比 (到不了100,会在 *倒计时时间* 后停止在 99)
 * @param duration 倒计时持续时间
 * @returns 进度条百分比 0 - 99
 */
function useFadeProgressPercent(duration: number) {
  const [countdown] = useCountDown({
    leftTime: duration,
    interval: 100,
  })

  // 1 - e^(-5) = 0.9932620530009145
  const alpha = 5

  const percent = useMemo(() => {
	const x = (duration - countdown)) / duration)

    return Math.floor(
      (1 - Math.exp((-alpha * x) * 100
    )
  }, [countdown, duration])

  return percent
}

其中,本文略去了useCountDown等细节,你可以在线上演示的代码中查看更多。