如何为自定义Circular Progress Bar添加跟随进度的圆点
嘿,这个需求很好实现!我们可以借助SVG的<circle>元素做那个跟随进度的圆点,再用一点点JS计算位置就行。下面是具体的修改方案:
第一步:修改HTML,添加圆点元素
在你的SVG里新增一个小圆形,用来做进度末端的圆点:
<div class="storage_counter_holder"> <svg> <circle cx="50%" cy="50%" r="48.5%"></circle> <circle cx="50%" cy="50%" r="48.5%"></circle> <!-- 新增的进度圆点 --> <circle class="progress-dot" cx="0" cy="0" r="6" fill="#15385f"></circle> <text x="50%" y="40%" dominant-baseline="middle">5,2/10 TB</text> <text x="50%" y="55%" dominant-baseline="middle">available storage</text> </svg> </div>
第二步:调整CSS,给圆点加基础样式
给圆点补一些样式,重点设置transform-origin为中心,方便后续旋转定位:
.storage_counter_holder svg { fill: none; stroke-width: 4; stroke-dasharray: 534; stroke-linecap: round; width: 100%; height: 100%; } .storage_counter_holder svg circle { transform: rotate(154deg); transform-origin: center; } .storage_counter_holder svg circle:nth-child(1) { stroke-dashoffset: 200; stroke: lightgray; } .storage_counter_holder svg circle:nth-child(2) { stroke-dashoffset: 340; /*calc(440 - (440 * 87) / 100);*/ stroke: #15385f; } .storage_counter_holder svg text { fill: #3D3D3D; text-anchor: middle; } .storage_counter_holder svg text:nth-child(3) { font-size: 24px; font-family: "Regular Fira Sans"; } .storage_counter_holder svg text:nth-child(4) { font-size: 16px; font-family: "Light Fira Sans"; } /* 进度圆点专属样式 */ .storage_counter_holder .progress-dot { fill: #15385f; /* 和进度条颜色保持一致 */ transform-origin: center; /* 以SVG中心为旋转原点 */ }
第三步:用JS计算圆点的动态位置
核心思路是根据进度条的stroke-dashoffset计算已绘制的长度,再转换成角度,最后通过旋转圆点让它精准落在进度末端:
function updateProgressDot() { // 获取元素 const holder = document.querySelector('.storage_counter_holder'); const progressCircle = holder.querySelector('circle:nth-child(2)'); const dot = holder.querySelector('.progress-dot'); // 读取环形进度的关键参数(也可以改成CSS变量更灵活) const totalLength = 534; // 对应stroke-dasharray的值 const startAngle = 154; // 对应circle的初始rotate角度 const circleRadius = '48.5%'; // 环形的半径 // 计算已绘制的进度长度 const offset = parseFloat(getComputedStyle(progressCircle).strokeDashoffset); const drawnLength = totalLength - offset; // 把长度转换成角度,再加上起始角度得到圆点的旋转角度 const drawnAngle = (drawnLength / totalLength) * 360; const totalRotation = startAngle + drawnAngle; // 设置圆点的位置和旋转 dot.setAttribute('cx', `calc(50% + ${circleRadius})`); dot.setAttribute('cy', '50%'); dot.style.transform = `rotate(${totalRotation}deg)`; } // 页面加载时初始化圆点位置 updateProgressDot();
动态更新的小提示
如果后续你需要修改进度(比如通过JS改变stroke-dashoffset),只要每次修改完后调用updateProgressDot(),圆点就会自动跟着进度移动啦!
要是想让参数更易维护,还可以把totalLength、startAngle这些值改成CSS变量,比如在.storage_counter_holder里加--total-length: 534;,然后在JS里用getComputedStyle(holder).getPropertyValue('--total-length')读取就行~
内容的提问来源于stack exchange,提问作者Ivan
相关产品推荐
相关产品推荐

