一个玻璃进度环的js源代码
我们平时在很多网站或者应用程序里,应该都见过各种各样的进度条,比如下载文件、加载数据时常见的那种。但这段代码特别的地方在于,它不仅展示了进度,而且加上了一层“玻璃”效果,这种透明、模糊的感觉瞬间就提升了整个视觉效果的高级感。
这段代码实现了一个带有玻璃效果的SVG进度环,它看起来非常酷炫,尤其在深色背景下,显得很科技感。通过一些动画和渐变,打造出光滑、透亮的视觉体验。
今天就和大家分享一下这个效果的实现,顺便写写我是如何解析这段代码的,也给大家一点思路,万一以后面试或者做项目的时候能用到呢。
核心实现思路
我知道,光说不练假把式,直接上源码会更直观。我简单梳理了一下整个代码的实现,主要分为几个部分:基础样式、SVG进度环的设计、动画的控制。接下来我逐步讲解。
1. 样式定义
在CSS中,开发者用了很多变量来管理颜色和动画时间:
:root {
--hue: 223;
--bg: hsl(var(--hue), 90%, 10%);
--fg: hsl(var(--hue), 90%, 90%);
--primary: hsl(var(--hue), 90%, 50%);
--trans-dur: 0.3s;
--trans-timing: cubic-bezier(0.65, 0, 0.35, 1);
font-size: calc(16px + (24 - 16) * (100vw - 320px) / (2560 - 320));
}
这些CSS变量用来定义颜色主题,利用HSL颜色模型,可以很方便地修改整体的色调。--hue
是控制色相的,通过调整这个值,能轻松切换环形进度条的颜色。这里的--bg
和--fg
分别是背景和前景色,而--primary
是进度环的主色调。
font-size
也非常巧妙,它根据视口宽度进行动态调整,保证在不同屏幕上字体大小都合适。是不是觉得特别细腻?别急,这只是开始。
2. SVG进度环
SVG是核心的部分,这个环形进度条就是通过SVG图形来绘制的。让我们仔细看看这一部分的代码:
<svg class="pl" viewBox="0 0 270 270" width="270px" height="270px" role="img" aria-labelledby="pl-percent">
<g fill="none">
<g transform="rotate(-90,135,135)">
<circle class="pl__ring" r="105" cx="135" cy="135" stroke-dasharray="659.74 659.74" stroke-dashoffset="659.74" stroke-width="40" />
<g filter="url(#glass-glow)" stroke-linecap="round" stroke-width="4" opacity="0.6">
<circle class="pl__ring-glow1" r="80" cx="135" cy="135" stroke-dasharray="502.66 502.66" stroke-dashoffset="502.66" />
<circle class="pl__ring-glow2" r="130" cx="135" cy="135" stroke-dasharray="816.82 816.82" stroke-dashoffset="816.82" />
</g>
</g>
</g>
</svg>
这段代码用到了<circle>
元素来绘制圆形进度条。几个重要参数:
r="105"
:定义了圆的半径,105px。cx="135"
和cy="135"
:定义了圆心的坐标,135px。stroke-dasharray
:这个属性控制了圆形边线的绘制方式,659.74
是圆周长,它通过控制线条的“虚线”状态来模拟进度。
stroke-dashoffset
是控制进度的核心,它的值根据百分比(--percent
)动态变化。当stroke-dashoffset
为圆周长时,进度是0%,当它为0时,表示进度完成。
同时,代码中使用了多个滤镜来增强视觉效果,比如模糊和渐变,让整个环看起来有种玻璃的透明质感。尤其是filter="url(#glass-glow)"
,它在进度环的周围增加了一层微光效果,这样看起来更加真实。
3. 动画效果
有了进度环之后,还需要动画来让它“动起来”,这就是JavaScript的活儿了。我们来看看代码里的JS部分:
window.addEventListener("DOMContentLoaded", () => {
const gpr = new GlassProgressRing(".pl");
const replayBtn = document.querySelector("#replay");
replayBtn?.addEventListener("click", gpr.replay.bind(gpr));
});
class GlassProgressRing {
constructor(el) {
this.el = document.querySelector(el);
this.complete = false;
this.percent = 0;
this.init();
}
init() {
this.progressDisplay();
this.loop();
}
loop() {
if (!this.complete) {
this.progressInc();
setTimeout(this.loop.bind(this), 17); // 每帧更新进度
}
}
progressInc(amount = 0.01) {
this.percent += amount;
if (this.percent >= 1) {
this.percent = 1;
this.complete = true;
}
this.progressDisplay();
}
progressDisplay() {
this.el.style.setProperty("--percent", this.percent);
const percentText = `${Math.round(this.percent * 100)}%`;
const percentEl = this.el.querySelector("[data-percent]");
percentEl.innerHTML = percentText;
}
replay() {
this.complete = false;
this.percent = 0;
this.init();
}
}
这里,JavaScript控制了整个进度环的动画过程。progressInc()
函数是每次递增进度的关键部分,每次增加0.01,也就是1%的进度,直到percent
达到1。
关键是setTimeout()
,通过每隔17毫秒调用一次loop()
函数,实现了进度条的平滑过渡。为什么是17毫秒?因为这相当于每秒60帧,符合大部分屏幕的刷新率,所以动画看起来会特别流畅。
4. 技术难点解析
这个项目其实有几个技术细节需要注意:
- SVG的动画控制:通过CSS变量
--percent
和stroke-dashoffset
的配合,控制了SVG环形进度条的绘制进度。这种做法非常高效,尤其是在处理矢量图形时,能大幅提升性能。 - 渐变和模糊滤镜的运用:这个玻璃效果主要通过
<filter>
和<linearGradient>
实现,这部分的实现比较复杂,细节上要保证渐变色的过渡自然,滤镜效果适中,才能达到预期的玻璃质感。 - 响应式设计:整个代码是自适应的,字体大小、颜色等都使用了CSS变量,可以根据不同的屏幕尺寸动态调整,保证了良好的兼容性。
结语
这段代码不复杂,但是细节处理得非常到位,从颜色到动画再到交互,整体效果非常流畅。通过这段代码,我们不仅能学习到如何利用SVG创建炫酷的UI组件,还能掌握一些CSS动画和滤镜的技巧。
如果你觉得这个进度环有意思,可以把代码复制下来,直接放到自己的项目里玩一玩。如果你愿意再改进一下,比如加点不同的色彩、控制动画速度,甚至是结合业务场景动态显示进度,那这个组件的实际价值会变得更大。