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

如何使用CSS/JS实现动态双色环形图标效果

实现方案

我们可以用SVG配合少量JS实现该效果,完全不需要依赖图片资源,调整也很灵活。

核心思路

用SVG的<circle>元素绘制环形,通过stroke-dasharray、stroke-dashoffset属性控制环形的显示比例,不同状态的环形通过类名切换颜色/渐变即可。

完整代码示例

HTML

<!-- 环形容器,图标会动态插入到这里 -->
<div class="icon-ring-container"></div>

<!-- 提前定义环形用到的蓝色渐变,复用即可 -->
<svg width="0" height="0" style="position: absolute;visibility: hidden;">
  <defs>
    <linearGradient id="blueGradient" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%" stop-color="#4285f4" />
      <stop offset="100%" stop-color="#1a73e8" />
    </linearGradient>
  </defs>
</svg>

CSS

.icon-ring-container {
  display: flex;
  gap: 20px;
  padding: 20px;
}
.ring-item {
  position: relative;
  width: 60px;
  height: 60px;
}
.ring-svg {
  width: 100%;
  height: 100%;
  transform: rotate(-90deg); /* 让环形的起点在顶部 */
}
.ring-circle {
  fill: none;
  stroke-width: 4; /* 环形的粗细,可自行调整 */
  r: 26; /* 环形半径 = 容器宽度/2 - stroke-width,这里60/2-4=26 */
  cx: 30;
  cy: 30;
}
/* 全灰状态 */
.ring-circle.gray {
  stroke: #e0e0e0;
}
/* 半完成状态的蓝色部分 */
.ring-circle.blue-part {
  stroke: #1a73e8;
}
/* 全完成渐变状态 */
.ring-circle.gradient-blue {
  stroke: url(#blueGradient);
}
/* 中间的图标占位,你可以换成自己的img或者iconfont */
.ring-icon {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: #f5f5f5;
  display: flex;
  align-items: center;
  justify-content: center;
}

JS

// 环形周长 = 2 * π * r,r是上面定义的26
const RING_CIRCUMFERENCE = 2 * Math.PI * 26;

/**
 * 生成单个环形图标
 * @param {number} index 当前图标索引
 * @param {number} total 总图标数量
 */
function generateRingItem(index, total) {
  const item = document.createElement('div');
  item.className = 'ring-item';
  
  // 生成环形SVG
  const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
  svg.className = 'ring-svg';
  
  // 先加底层全灰背景环
  const bgCircle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
  bgCircle.className = 'ring-circle gray';
  svg.appendChild(bgCircle);

  if (index === total - 1) {
    // 最后一个图标:全蓝色渐变环形
    const fullCircle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
    fullCircle.className = 'ring-circle gradient-blue';
    fullCircle.style.strokeDasharray = RING_CIRCUMFERENCE;
    fullCircle.style.strokeDashoffset = 0;
    svg.appendChild(fullCircle);
  } else if (index !== 0) {
    // 中间图标:灰蓝拼接,这里默认蓝色占50%,可以根据实际业务调整比例
    const halfCircle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
    halfCircle.className = 'ring-circle blue-part';
    halfCircle.style.strokeDasharray = RING_CIRCUMFERENCE;
    halfCircle.style.strokeDashoffset = RING_CIRCUMFERENCE * 0.5; // 0.5就是蓝色占一半,改这个数值调整比例
    svg.appendChild(halfCircle);
  }

  // 加中间的图标占位
  const icon = document.createElement('div');
  icon.className = 'ring-icon';
  icon.innerText = index + 1; // 换成你的图标内容即可

  item.appendChild(svg);
  item.appendChild(icon);
  return item;
}

/**
 * 初始化所有环形图标
 * @param {number} total 要生成的图标总数量
 */
function initRings(total) {
  const container = document.querySelector('.icon-ring-container');
  container.innerHTML = '';
  for(let i = 0; i < total; i++) {
    container.appendChild(generateRingItem(i, total));
  }
}

// 示例:生成5个图标,要改数量直接传不同的参数就行
initRings(5);

需求匹配说明

  • 图标数量动态可变:直接调用initRings(数量)即可生成对应数量的图标,完全灵活
  • 第一个图标全灰色:默认底层就是全灰环,第一个不叠加其他颜色环,自然就是全灰效果
  • 中间图标灰蓝拼接:底层灰环+上层蓝色部分环,拼接效果自动实现,蓝色占比可以调整strokeDashoffset的系数自行修改
  • 最后一个图标蓝色渐变:直接使用预定义的SVG渐变填充环形即可
  • 所有环形都是动态生成的SVG元素,没有嵌入到图片中,修改样式、调整比例都非常方便

内容的提问来源于stack exchange,提问作者Davina Leong

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 02:06:01