专栏名称: 前端早读课
我们关注前端,产品体验设计,更关注前端同行的成长。 每天清晨五点早读,四万+同行相伴成长。
目录
相关文章推荐
前端早读课  ·  【第3430期】CSS 如何模拟“真实的”进度条? ·  23 小时前  
前端早读课  ·  【早阅】浏览器扩展程序攻击 ·  昨天  
奇舞精选  ·  奇舞周刊第545期:React 19 正式发布 ·  5 天前  
奇舞精选  ·  奇舞周刊第545期:React 19 正式发布 ·  5 天前  
太星小升初  ·  紧急提醒!不得带病上岗上课! ·  5 天前  
太星小升初  ·  紧急提醒!不得带病上岗上课! ·  5 天前  
51好读  ›  专栏  ›  前端早读课

【第3430期】CSS 如何模拟“真实的”进度条?

前端早读课  · 公众号  · 前端  · 2024-12-11 08:00

正文

前言

介绍了如何使用 CSS 模拟真实的进度条,并提供了具体的实现方法和技巧。今日前端早读课文章由 @XboYan 分享,公号:前端侦探授权。

正文从这开始~~

在页面加载过程中,进度条的存在可以很好的缓解用户的等待焦虑。

【第3429期】css-doodle 介绍

但是你可能不知道,90% 以上的进度条只是模拟的,是假的进度条。没办法,大部分情况下都无法真实的算出资源的加载情况。既然无法避免,那我们就需要尽可能真实地模拟加载情况,给人一种页面很轻快的感觉。

在这里,我们可以仅使用 CSS 来模拟一个比较真实的进度条加载,一起看看吧

一、进度条加载和 CSS 缓冲动画

进度条的实现很简单,我们仅需要一个容器就行了,例如

 <div class="progress">div>

这里有两层结构,我们可以用一层伪元素来表示当前进度

 .progress{
position: relative;
width: 300px;
height: 10px;
margin: 25px 0;
border-radius: 10px;
overflow: hidden;
background-color: #E4CCFF;
}
.progress::before{
position: absolute;
content: '';
width: 0%;
height: 100%;
background: #9747FF;
}

这样我们就绘制了两层,可以通过改变::before 的宽度来改变当前进度,要实现进度从 0% -> 100% 非常简单,只需要一个关键帧就行了

 .progress::before{
animation: progress 10s forwards;
}
@keyframes progress {
to {
width: 100%
}
}

效果如下

这是默认的缓冲效果,也就是 ease

这是一种先快后慢的运动效果,其实也基本符合我们的需求,至少比匀速要好很多,例如下面是 ease 和 linear 的对比,虽然总时长相同,但很明显 ease 给人的感觉更快。

为了便于区分是否完成,我们在最后一个进度将进度条变为绿色

 @keyframes progress {
99%{
background-color: #9747FF;
}
100%{
background-color: #14AE5C;
width: 100%;
}
}

效果如下

不过,仅仅是 ease 还不够,我们可以将起始速度调整的更快,这个可以通过 cubic-bezier 实现,比如这样一个曲线

前半段速度足够快,后半段足够慢,几乎处于停止状态,下面来对比一下这 3 者的效果

是不是感觉这个进度条更快了呢?

二、使用 linear 实现更精细的进度控制

前面的 cubic-bezier 虽然能实现先快后面的效果,但整体还是比较单调,毕竟没什么细节。

【第3413期】2024年CSS状态调查报告

实际的加载过程可能会受到网络环境的影响,速度时快时慢,甚至会在中途停止一小会,这种有什么办法模拟呢?当然也是有的,这需要借助全新的 linear() 函数

简单来说,就是我们可以通过 linear 设置足够多的细节,来尽可能真实地模拟加载情况。

下面是我在 Chrome 控制台上随便加了十几个关键点,有些点前后纵向距离比较接近,就表示这段时间内运动的距离很短,也就是速度很慢,可以模拟出卡顿的感觉,你也可以根据自己或者设计的感觉加入更多的关键点

下面来看一下这个缓冲效果和前面的对比

是不是看着更像那么一回事了,有种网络不稳定的感觉?

不过,这个 linear 的兼容性还有点差,实际中可以做一下兼容,不支持的仍然可以用前面的 cubic-ezier 方式,类似于这样,毕竟是渐进增强而已

 .progress {
--ease: cubic-bezier(.08,.81,.29,.99);
}
@supports (animation-timing-function: linear(0, 1)) {
.progress {
--ease: linear(0 0%, 0.25 4.14%, 0.53 13.29%, 0.61 25.03%, 0.75 34.8%, 0.88 43.99%, 0.93 58.77%, 0.98 68.88%, 0.99 79.22%, 1 88.79%, 1 100%);
}
}

三、主动完成进度条

大多数情况下,进度条只是一个过渡状态,不会真正等到进度条走完,我们可能在监听到某个关键资源加载成功或者某个功能初始化成功的实现就直接让进度条走完(1s 内),这该如何处理呢?

直接替换肯定不行,那样就不够平滑了,动画也不够连贯。

这里有个非常巧妙的方式,也非常简单。

给进度条额外增加一个相同的动画,就是时间不一样,之前的是 10s,新加的时长比较短,只有 1s,默认情况下,只有前面的动画是执行的,后面的动画是暂停的,这里用一个单独的 CSS 变量来指定暂停状态,实现如下

 .progress::before{
/*两个相同的动画,播放时长不同*/
animation: progress 10s var(--ease) forwards, progress 1s var(--ease) forwards;
animation-play-state: var(--running, running, paused);
}

然后在某个时刻,资源加载完成的时候,改变一下播放状态,让前面的暂停,后面的开始播放,后面的动画时长只有 1s,所以很快就能完成,这里用点击事件来模拟加载完成

 btn.onclick = function(){
document.body.style.setProperty('--running', 'paused, running')
}

这样在点击之后,可以在 1s 内平滑地完成整个进度,效果如下

还可以改变以下后面动画的缓冲效果,也就是在 “立刻完成” 之后,全部都用默认的 ease,而不是和前面保持一致

 .progress::before{
position: absolute;
content: '';
width: 0%;
height: 100%;
background: #9747FF;
animation: progress var(--dur, 10s) var(--ease) forwards, progress 1s forwards;
}

这样会不会更好一点呢?(“立即完成” 后不应该有网络波动的感觉🤔)

以上完整代码可以查看以下 demo:https://codepen.io/xboxyan/pen/emOmazz

四、总结一下

这样一个非常实用的进度条模拟小技巧,你学到了吗?下面总结一下

  • 进度条可以用户的等待焦虑

  • 大多数情况下无法真实的算出资源的加载情况,所以需要尽可能真实的模拟进度加载情况

  • CSS 动画默认的 ease 是先快后面,给人一种加载快的感觉

  • 还可以通过 cubic-bezier 让初始速度更快

  • 通过 linear 可以给进度添加更多细节,以便于模拟更复杂的加载情况

  • 实际页面上进度条只是一个过渡状态,不会真正等到进度条走完,需要主动触发完成进度条

  • 直接改成进度条状态不够平滑,动画也不够连贯

  • 可以通过多动画,设置不同的动画时长,在真正需要完成的时候改变动画暂停状态,来实现主动完成进度加载

关于本文
作者:@XboYan
原文:https://mp.weixin.qq.com/s/LIDMxVSqBhT1RX41WnCKHg

这期前端早读课
对你有帮助,帮” 
 “一下,
期待下一期,帮”
 在看” 一下 。