【问题标题】:How to remove space between svg based pie chars slices?如何删除基于 svg 的饼图字符切片之间的空间?
【发布时间】:2016-12-09 00:09:09
【问题描述】:

我有这个代码基于 Lea Verou svg based pie chart 使用 Angular

angular.module('app', []).controller('main', function() {
    // taken from api
    var counters = {
        "missingAuthorSignature": 60,
        "missingWitnessSignature": 70,
        "pendingWitnessSignoff": 8,
        "entitiesTotalCreated": 83,
        "entitiesArchived": 0,
        "entitiesCompleted": 12,
        "entitiesIncomplete": 71,
        "entitiesWitnessed": 38
    };
    this.activity = {
        color: '#1F187A',
        data: [{
            color: '#3D38A4',
            value: counters.entitiesArchived
        }, {
            color: '#645EDB',
            value: counters.entitiesCompleted
        }, {
            color: '#8781FF',
            value: counters.entitiesIncomplete
        }, {
            color: '#828591',
            value: counters.entitiesWitnessed
        }]
    };
    // this part is taken from piechart component
    this.parts = this.activity.data.slice();
    this.all = {
        value: this.parts.reduce((count, part) => {
            return count + part.value;
        }, 0),
        color: this.activity.color
    };
    this.parts.forEach((part) => {
        part.value = part.value * 360 / this.all.value;
    });
    for (var i = 0; i < this.parts.length; ++i) {
        this.parts[i].offset = Math.round(this.parts.slice(0, i).reduce((count, part) => {
            return count + part.value;
        }, 0));
    }
});
svg {
    width: 140px; height: 140px;
    transform: rotate(-90deg);
    border-radius: 50%;
}
circle {
    fill: transparent;
    stroke-width: 116;
    transform-origin: 50% 50%;
}
#center {
    r: 25;
    stroke: white;
    stroke-width: 5;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<div ng-app="app" ng-controller="main as vm">
<svg viewBox="0 0 116 116">
  <circle id="circle-{{$index}}" r="58" cx="58" cy="58" ng-repeat="part in vm.parts"
          ng-style="{transform: 'rotate({{part.offset}}deg)'}" stroke="{{part.color}}"
          ng-attr-stroke-dasharray="{{part.value}} 360" />
  <circle id="center" cx="58" cy="58" ng-style="{fill: vm.all.color}" />
  <g transform="translate(58,58) rotate(90) translate(0, -45)">
  	<text y="50" font-family="Arial" fill="white">
       <tspan x="0" text-anchor="middle">{{vm.all.value}}</tspan>
  	</text>
  </g>
</svg>
</div>

运行 sn-p 时可以看到,切片之间存在间隙,是否可以将其移除?

【问题讨论】:

  • 看起来半圆错位了一两个像素。还是未正确创建 SVG?
  • 这不是一个真正的解决方案,但我想我可以告诉你问题是什么:stroke-dasharray 不是 100% 准确的。您的示例中使用的方法依赖于该属性,该属性指定笔划中破折号之间的间隙宽度。您可以通过将列表减少到仅一项活动来了解为什么这是一个问题。你会看到stroke-dasharray 的值为`360 360。这应该在第一个间隙之前给你一个 360 度的破折号,但是 chrome 不能很好地处理这个值。它仍然试图为“破折号”添加一个间隙。这就是问题的根源。度数在这里并不精确。

标签: javascript css angularjs svg pie-chart


【解决方案1】:

我已通过在计算偏移量时将 3 添加到 value 并在每个步骤中减去 3 来解决此问题:

            this.parts.forEach((part) => {
                part.value = part.value * 360 / this.all.value + 3;
            });
            for (var i=0; i<this.parts.length; ++i) {
                this.parts[i].offset = Math.floor(this.parts.slice(0, i).reduce((count, part) => {
                    return count + part.value - 3;
                }, 0));
            }

【讨论】: