使用 HTML5 Canvas API 实现的对称 288° 圆环进度条,支持颜色渐变和平滑动画。
| 技术 | 说明 |
|---|---|
| 绘制方法 | ctx.arc() 绘制圆弧 |
| 样式设置 | strokeStyle、lineWidth、lineCap |
| 坐标系统 | 以画布中心为原点,使用极坐标计算 |
| 参数 | 值 | 说明 |
|---|---|---|
| 起始角度 | -144° | 7点钟方向(相对于12点) |
| 结束角度 | 144° | 5点钟方向(相对于12点) |
| 总角度 | 288° | 占完整圆的 80% |
| 空白区域 | 72° | 144° 到 216° 之间 |
角度计算公式:
角度 = -144° + 进度百分比 × 288° / 100
.progress-wrapper {
transform: rotate(-90deg); /* 向左旋转90度 */
}
.progress-info {
transform: rotate(90deg); /* 文字反向旋转保持正常 */
}
原理:整个容器旋转 -90°,使 Canvas 的 0° 基准位于 12 点钟方向,文字区域反向旋转保持可读性。
const colorStops = [
{percent: 0, color: '#FFC900'}, // 黄色
{percent: 11, color: '#FFC900'},
{percent: 32, color: '#13A6FF'}, // 蓝色
{percent: 50, color: '#806EFF'}, // 紫色
{percent: 66, color: '#FF8EEC'}, // 粉色
{percent: 89, color: '#FE4F51'}, // 红色
{percent: 100, color: '#FE4F51'}
];
t = (percent - startPercent) / (endPercent - startPercent)R = R1 + (R2 - R1) × t核心思路:将圆弧分成多段,每段使用不同颜色,实现平滑渐变效果。
// 计算分段数量(根据进度动态调整)
const segmentCount = Math.max(20, Math.floor(progress * 0.5));
// 分段绘制
for (let i = 0; i < segmentCount; i++) {
const segmentStart = startAngleRad + (angleRange * i / segmentCount);
const segmentEnd = startAngleRad + (angleRange * (i + 1) / segmentCount);
const segmentCenterPercent = (i + 0.5) / segmentCount * progress;
const segmentColor = getColorForPercent(segmentCenterPercent);
ctx.strokeStyle = segmentColor;
ctx.arc(centerX, centerY, radius, segmentStart, segmentEnd);
ctx.stroke();
}
const easing = 0.1;
currentProgress += (targetProgress - currentProgress) * easing;
requestAnimationFrame 实现平滑动画drawProgress() 重绘画布drawProgress(progress)
├── clearRect() // 清空画布
├── drawBackgroundRing() // 绘制背景圆环和空白区域指示
├── 计算结束角度
├── 分段绘制进度条(渐变)
├── 绘制起点/终点标记(100%时)
├── drawProgressText() // 绘制中心文字
└── updateUIDisplay() // 更新UI元素
| 函数 | 功能 |
|---|---|
drawProgress(progress) |
主绘制函数,绘制完整进度条 |
getColorForPercent(percent) |
根据百分比获取插值颜色 |
interpolateColor(c1, c2, t) |
RGB 颜色线性插值 |
calculateAngle(progress) |
将进度百分比转换为角度 |
animateProgress() |
动画循环函数 |
updateProgress(newProgress) |
更新目标进度并启动动画 |
requestAnimationFrame 优化渲染性能| 功能 | 实现方式 |
|---|---|
| 滑块控制 | input[type="range"] 监听 input 事件 |
| 测试按钮 | 预设百分比值快速测试 |
| 动画演示 | 从 0% 到 100% 自动播放 |
| 随机进度 | 生成 0-100 随机值 |
角度 × Math.PI / 180