You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 03:28:24