如何让SVG环形图(Donut Chart)的所有弧段无缝连接?
解决SVG环形图(circle元素)弧段间隙问题
你的问题出在偏移量计算错误,以及元素位置未对齐,导致弧段之间出现间隙。以下是修正方案:
问题根源
- 偏移量计算中多余的
1 * i:这会让每个切片的起始位置额外偏移i个单位,强制拉开了切片间隙。 - circle元素位置未与SVG viewBox中心对齐:导致环形图整体偏移,可能加剧视觉上的间隙感。
- pathLength的冗余设置:不需要结合数组长度计算,统一设为100即可让百分比直接对应dash长度。
修正后的完整代码
JavaScript
var DonutSlice = [{ id: 1, percent: 60, color: 'DarkSeaGreen', label: 'Slice 1' }, { id: 2, percent: 30, color: 'DarkOrchid', label: 'Slice 2' }, { id: 3, percent: 10, color: 'Tomato', label: 'Slice 3' } ]; var circlecontainer = document.getElementById('circlecontainer'); var output = document.getElementById('output'); circlecontainer.innerHTML = DonutSlice.map((item, i, arr) => { // 去掉多余的1*i,仅计算前面所有切片的百分比总和作为偏移 let offset = arr.filter((item, j) => j < i) .reduce((total, item) => total + item.percent, 0); return `<circle data-id="${item.id}" stroke="${item.color}" cx="87" cy="87" r="79" class="slice" pathLength="100" stroke-dasharray="${item.percent} 100" stroke-dashoffset="-${offset}" />`; }).join(''); circlecontainer.addEventListener('mouseover', e => { let slice = e.target.closest('.slice'); if (slice) { item = DonutSlice.find(item => item.id == parseInt(slice.dataset.id)); output.innerHTML = `${item.label} was hovered`; } });
CSS
.slice { /* stroke-linecap: round; */ stroke-width: 15; fill: none; cursor: pointer; } p#output { text-align: center; }
HTML
<div style="width: 200px"> <svg class="svg2" width="174" height="174" preserveAspectRatio="xMinYMin meet" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 174 174" version="1.1"> <circle fill="#000000" cx="87" cy="87" r="87" /> <g id="circlecontainer" transform="rotate(-90 87 87)"></g> </svg> <p id="output"></p> </div>
额外优化说明
- 给
circlecontainer添加了rotate(-90 87 87):默认SVG环形的起始点在右侧,旋转-90度后起始点会移到顶部,符合常见环形图的视觉习惯。 - 修正了鼠标事件的提示文本:原代码写的是"clicked"但实际是mouseover事件,改为"hovered"更准确。
内容的提问来源于stack exchange,提问作者Ryan
相关产品推荐
相关产品推荐

