SVG彩色分段交互式环形图(带时钟动画)实现方案咨询
多分段SVG环形图:动画与交互实现方案
我刚接触SVG,想制作一个带多色分段的环形图(donut),要求:
- 各分段支持鼠标悬停变色/高亮
- 整体呈现类似时钟的绘制动画
尝试用单个<circle>通过stroke-dasharray和stroke-dashoffset实现分段,但添加CSS时钟动画后,所有分段颜色被最后一个分段覆盖。纠结是给每个分段单独创建<circle>,还是用<arc>构建,求方案建议。
现有代码
HTML
<svg id = "circleMenuViewBox" width = "100%" height = "100%" viewBox="-10 -10 100 100"> <defs> <circle id ="circlemenu" cx="10" cy="10" r="5" stroke-width="3" fill="none" stroke-dasharray="31.4"/> </defs> <use href="#circlemenu" stroke="#689689" stroke-dashoffset="0"/> <use href="#circlemenu" stroke="#83E8BA" stroke-dashoffset="7.85"/> <use href="#circlemenu" stroke="#B2E6D4" stroke-dashoffset="15.7"/> <use href="#circlemenu" stroke="#504136" stroke-dashoffset="23.55"/> </svg>
CSS
#circlemenu { fill: none; stroke-dasharray: 31.4; stroke-dashoffset: 31.4; animation: clock-animation 0.2s linear; animation-fill-mode: forwards; } @keyframes clock-animation { 0% { stroke-dashoffset: 31.4; } 100% { stroke-dashoffset: 0; } }
解决方案
核心问题是动画作用在了<defs>中的原始<circle>上,导致所有<use>引用继承了动画最终状态,覆盖了各自的stroke-dashoffset。以下是优化方案:
1. 调整动画目标与分段配置
将动画从原始<circle>转移到每个<use>分段上,同时给每个分段设置仅显示自身长度的stroke-dasharray:
修改后的HTML
<svg id="circleMenuViewBox" width="100%" height="100%" viewBox="-10 -10 100 100"> <defs> <circle id="circlemenu" cx="10" cy="10" r="5" stroke-width="3" fill="none" /> </defs> <!-- 每个分段配置:自身长度+全圆长度的dasharray,目标偏移量用CSS变量指定 --> <use href="#circlemenu" class="segment" stroke="#689689" stroke-dasharray="7.85 31.4" style="--target-offset: 0;" /> <use href="#circlemenu" class="segment" stroke="#83E8BA" stroke-dasharray="7.85 31.4" style="--target-offset: 7.85;" /> <use href="#circlemenu" class="segment" stroke="#B2E6D4" stroke-dasharray="7.85 31.4" style="--target-offset: 15.7;" /> <use href="#circlemenu" class="segment" stroke="#504136" stroke-dasharray="7.85 31.4" style="--target-offset: 23.55;" /> </svg>
注:全圆周长=2πr=31.4,每个分段占1/4,长度为7.85
修改后的CSS
.segment { stroke-dashoffset: 31.4; /* 初始状态隐藏整个分段 */ animation: clock-animation 0.2s linear forwards; transition: all 0.3s ease; /* 交互过渡效果 */ } /* 给分段添加动画延迟,模拟时钟依次扫过的效果 */ .segment:nth-child(2) { animation-delay: 0.2s; } .segment:nth-child(3) { animation-delay: 0.4s; } .segment:nth-child(4) { animation-delay: 0.6s; } @keyframes clock-animation { to { stroke-dashoffset: var(--target-offset); /* 动画结束后到达目标偏移量 */ } } /* 鼠标悬停交互效果 */ .segment:hover { stroke: #ffcc00; /* 悬停变色 */ stroke-width: 4; /* 加粗突出 */ }
2. 方案选型说明
- 用
<circle>+stroke-dash的方式更简洁,无需手动计算弧的角度参数,维护成本低,适合均匀分段的场景。 - 若需要非均匀分段或更复杂的形状,再考虑用
<path>绘制独立弧段。
内容的提问来源于stack exchange,提问作者g0m3z
相关产品推荐
相关产品推荐

