广告

CSS圆形进度条如何实现动态增长?用 stroke-dashoffset 搭配 keyframes 的动画实现教程

本文围绕 CSS圆形进度条如何实现动态增长?用 stroke-dashoffset 搭配 keyframes 的动画实现教程,聚焦实现思路、关键属性和完整代码示例,帮助你快速上手。

1. 原理与核心要点

1.1 圆环结构与路径长度

要实现圆形进度条,通常采用 SVG 的圆形(circle)作为基本路径,包含一个背景轨道和一个前景进度环。圆环的关键在于如何通过圆周长度来控制可见部分的长度,并让它在视觉上产生“增长”的效果。stroke-dasharray 可以把圆周分成若干段,stroke-dashoffset 则决定当前可见部分的起始偏移,结合起来就能实现隐藏/显示圆环的效果。

将圆周长记作 circumference,如果把 stroke-dasharray 设置为 circumference,同时把 stroke-dashoffset 设为 circumference,圆环将完全不可见。随后将 stroke-dashoffset 逐步减小到 0,就能得到从无到有的动态增长。

在实际实现中,通常会把圆环分为两部分:一个后台轨道(背景圆)和一个前景进度环(前景圆)。两者的 stroke-width、strokeLinecap、颜色和不透明度等属性应统一风格],以保持视觉一致性。


<svg width="120" height="120" viewBox="0 0 120 120" aria-label="圆形进度条"><circle cx="60" cy="60" r="54" class="bg-track" /><circle cx="60" cy="60" r="54" class="progress" />
</svg>

1.2 动画原理:stroke-dashoffset 与 keyframes

核心在于使用 @keyframes 结合 CSS 动画来改变 stroke-dashoffset 的值,达到“增长”的视觉效果。将初始偏移设为圆周长,终点设为 0,即可实现完整圆环从空到满的过程。

为了获得更平滑的边缘,可以开启 stroke-linecapround,并在动画完成后保持最终状态(使用 forwards 关键字)。此外,使用 CSS 自定义属性(变量)来保存圆周长,可以使同一份代码适配不同半径的圆环。


:root {--size: 120px;--stroke: 12;/* circumference = 2 * PI * r,其中 r = (size - stroke) / 2 */--circ: calc(2 * 3.1415926 * (var(--size) / 2 - var(--stroke) / 2));
}

1.3 动画参数的设计要点

在设计动画时,时长延迟、以及 缓动函数(如 cubic-bezier、ease、linear)会影响动态的流畅度与感知速度。对于进度条,一般采用 线性缓动 以确保增长过程均匀,避免加速或减速带来视觉错乱。

另外,考虑到可访问性,给 SVG 提供可读的 aria-valuenowaria-valuemaxaria-valuemin 属性,以及屏幕阅读器友好的文本提示,是一个良好的实践。


.progress {stroke: #3b82f6;stroke-width: var(--stroke);fill: none;stroke-linecap: round;stroke-dasharray: var(--circ);stroke-dashoffset: var(--circ);animation: grow 2s linear forwards;
}
@keyframes grow {to { stroke-dashoffset: 0; }
}

2. 使用 stroke-dashoffset 实现动态增长

2.1 定义圆周长与初始状态

为了让同一个样式适配不同尺寸的圆环,推荐通过 CSS 自定义属性保存圆周长。圆周长 作为进度的总长度,初始状态将 stroke-dashoffset 设置为同样的圆周长,以确保圆环一开始不可见。

在布局中,viewBox 与圆心坐标需要统一,确保圆环在中心对齐且等比缩放,从而在不同屏幕下保持一致的视觉效果。


<svg class="ring" viewBox="0 0 120 120" width="120" height="120" aria-label="进度圆"><circle cx="60" cy="60" r="54" class="bg-track"/><circle cx="60" cy="60" r="54" class="progress" />
</svg>

:root {--size: 120px;--stroke: 12;--circ: calc(2 * 3.1415926 * (var(--size) / 2 - var(--stroke) / 2));
}
.ring { width: var(--size); height: var(--size); transform: rotate(-90deg); }
.bg-track {fill: none;stroke: #e5e7eb;stroke-width: var(--stroke);
}
.progress {fill: none;stroke: #3b82f6;stroke-width: var(--stroke);stroke-linecap: round;stroke-dasharray: var(--circ);stroke-dashoffset: var(--circ);animation: progress 2s linear forwards;
}
@keyframes progress {to { stroke-dashoffset: 0; }
}

2.2 将圆周长绑定到实际尺寸

由于圆周长与圆半径相关,最好在页面加载后通过 JavaScript 计算实际的圆周长并写入自定义属性,从而实现对不同尺寸的适配与灵活控制。

通过绑定变量后,可以在需要时动态改变进度,例如通过更新 stroke-dashoffset 的值来实现任意百分比的进度展示。


// 假设使用 r = 54 的圆环
const radius = 54;
const circumference = 2 * Math.PI * radius;
document.documentElement.style.setProperty('--circ', circumference);

3. 通过 keyframes 实现增长动画

3.1 关键帧定义与时间函数

使用 @keyframes 定义一个简单的增长序列,起始状态为圆周长的偏移量,终点为 0。为了视觉顺滑,建议使用线性或轻微加速的缓动函数。

将关键帧应用到前景圆上,同时保留背景圆的静态状态,这样就能实现清晰分离的动态增长效果。


@keyframes progress {from { stroke-dashoffset: var(--circ); }to { stroke-dashoffset: 0; }
}

3.2 与交互结合的动效设计

除了页面加载时自动增长,你也可以把增长作为一个响应式交互事件的结果,例如用户输入的百分比、进度完成度、或滚动事件触发的进度更新。通过重新计算 circumference 或更新 CSS 变量,可以重用同一套 CSS 动画逻辑实现不同的进度值。


/* 根据百分比动态更新进度 */
.progress {stroke-dashoffset: calc(var(--circ) * (1 - var(--percent)));animation: none;
}

4. 实战示例:完整代码

4.1 完整的 HTML/CSS/JS 示例

下面给出一个完整、可直接运行的示例,包含 SVG 结构、样式、以及用于设置圆周长和进度的 JavaScript 逻辑,方便你直接在项目中复用。


<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>CSS 圆形进度条 动态增长示例</title><style>:root {--size: 120px;--stroke: 12;--circ: calc(2 * 3.1415926 * (var(--size) / 2 - var(--stroke) / 2));}.ring {width: var(--size);height: var(--size);transform: rotate(-90deg);}.bg-track {fill: none;stroke: #e5e7eb;stroke-width: var(--stroke);}.progress {fill: none;stroke: #3b82f6;stroke-width: var(--stroke);stroke-linecap: round;stroke-dasharray: var(--circ);stroke-dashoffset: var(--circ);animation: progress 2s linear forwards;}@keyframes progress {to { stroke-dashoffset: 0; }}</style>
</head>
<body><svg class="ring" viewBox="0 0 120 120" aria-label="圆形进度条示例"><circle class="bg-track" cx="60" cy="60" r="54"></circle><circle id="prog" class="progress" cx="60" cy="60" r="54"></circle>
</svg><script>// 动态设定圆周长,便于不同半径的圆环复用const r = 54;const circ = 2 * Math.PI * r;document.documentElement.style.setProperty('--circ', circ);// 示例:设置进度百分比(0-100)function setProgress(percent) {const clamped = Math.max(0, Math.min(100, percent));const dash = circ * (clamped / 100);const prog = document.getElementById('prog');prog.style.strokeDashoffset = circ - dash;}// 演示:从 0% 动画到 75%setProgress(75);
</script>
</body>
</html>

4.2 将示例应用到你自己的项目

将上述代码按模块化方式整合到你的前端工程中,可以通过以下步骤实现复用:提取圆环参数将百分比映射到 stroke-dashoffset、以及使用 @keyframes 提供一致的动画体验。通过改造 CSS 变量,你还可以实现不同尺寸、不同颜色主题的圆形进度条。

CSS圆形进度条如何实现动态增长?用 stroke-dashoffset 搭配 keyframes 的动画实现教程

以上内容围绕 CSS圆形进度条如何实现动态增长?用 stroke-dashoffset 搭配 keyframes 的动画实现教程展开,涵盖原理、实现要点和完整示例,帮助你快速掌握在网页中创建优雅的圆形进度条动画。

广告