d3圆环图的标签

时间:2018-01-16 11:53:14

标签: d3.js svg

我正在使用d3 js创建圆环图。我正在尝试向弧线添加角度标签,如下图所示

enter image description here

这是我的工作代码



var width = 300,
    height = 300,
    radius = Math.min(width, height) / 2;

var color = d3.scale.ordinal()
    .range(["#6fc9e1", "#00627d", "#179bbf"]);

var biggestarc = d3.svg.arc()
    .outerRadius(radius - 100)
    .innerRadius(radius - 60);

var bigarc = d3.svg.arc()
    .outerRadius(radius - 100)
    .innerRadius(radius - 50);

var smallarc = d3.svg.arc()
    .outerRadius(radius - 100)
    .innerRadius(radius - 40);
    
/*var biggerarc = d3.svg.arc()
    .outerRadius(radius - 80)
    .innerRadius(radius - 70);*/



var pie = d3.layout.pie()
    .sort(null)
    
    .value(function (d) {
    return d.percent;
});

var svg = d3.select("#donut").append("svg")
    .attr("width", width)
    .attr("height", height)
    .append("g")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");



data = [{
    "label": "Biggest",
        "percent": 33
}, {
    "label": "Big",
    "percent": 17
}, {
    "label": "Small",
    "percent": 50
}]

var g = svg.selectAll(".arc")
    .data(pie(data))
    .enter().append("g")
    .attr("class", "arc");

g.append("path")
    .attr("d", function (d) {
    
    if (d.data.label == "Biggest") {
        return biggestarc(d);

    } else if (d.data.label == "Big") {
        return bigarc(d);

    } else {
        
        return smallarc(d);
    }
})

 

.style("fill", function (d) {
    return color(d.data.label);
});
g.append("text")                                     //add a label to each slice
                .attr("transform", function(d) {  
                  //set the label's origin to the center of the arc
                d.innerRadius = 0;
                d.outerRadius = radius;
                if (d.data.label == "Biggest") {
                    return "translate(" + biggestarc.centroid(d) + ")"; 
            
                }
                else if (d.data.label == "Big") {
                    return "translate(" + bigarc.centroid(d) + ")"; 
            
                }
                else{
                    return "translate(" + smallarc.centroid(d) + ")"; 
            
                }
                      
            })
            .attr("text-anchor", "middle") 
            .text(function(d, i) { 
              
              return data[i].percent + '%';
               
              
            })

body {
    font: 10px sans-serif;
}
.arc path {
    stroke: #fff;
}
text {
    font-size:12px
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.3.0/d3.min.js"></script>
<div id="donut"></div>
&#13;
&#13;
&#13;

刚刚获得this链接并尝试实现。在我探索d3 js时,正在努力做到这一点。有人可以帮我吗?

1 个答案:

答案 0 :(得分:2)

计算所有必需的坐标将有助于您在正确的位置绘制标签和指针(path)。

我准备回答另一个类似的问题:Donut labels with connectors

不是再次为您提供链接,而是使用该方法的代码片段(我认为它比我之前提到的polyline方法更简单。

var width = 300,
    height = 300,
    radius = Math.min(width, height) / 2;

var color = d3.scale.ordinal()
    .range(["#6fc9e1", "#00627d", "#179bbf"]);

var biggestarc = d3.svg.arc()
    .outerRadius(radius - 100)
    .innerRadius(radius - 60);

var bigarc = d3.svg.arc()
    .outerRadius(radius - 100)
    .innerRadius(radius - 50);

var smallarc = d3.svg.arc()
    .outerRadius(radius - 100)
    .innerRadius(radius - 40);
    
/*var biggerarc = d3.svg.arc()
    .outerRadius(radius - 80)
    .innerRadius(radius - 70);*/



var pie = d3.layout.pie()
    .sort(null)
    
    .value(function (d) {
    return d.percent;
});

var svg = d3.select("#donut").append("svg")
    .attr("width", width)
    .attr("height", height)
    .append("g")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");



data = [{
    "label": "Biggest",
        "percent": 33
}, {
    "label": "Big",
    "percent": 17
}, {
    "label": "Small",
    "percent": 50
}]

var piedata = pie(data);

var g = svg.selectAll(".arc")
    .data(piedata)
    .enter().append("g")
    .attr("class", "arc");

g.append("path")
    .attr("d", function (d) {
    
    if (d.data.label == "Biggest") {
        return biggestarc(d);

    } else if (d.data.label == "Big") {
        return bigarc(d);

    } else {
        
        return smallarc(d);
    }
}).style("fill", function (d) {
    return color(d.data.label);
});

g.append("text")                                     //add a label to each slice
                .attr("transform", function(d) {  
                  //set the label's origin to the center of the arc
                d.innerRadius = 0;
                d.outerRadius = radius;
                if (d.data.label == "Biggest") {
                    return "translate(" + biggestarc.centroid(d) + ")"; 
            
                }
                else if (d.data.label == "Big") {
                    return "translate(" + bigarc.centroid(d) + ")"; 
            
                }
                else{
                    return "translate(" + smallarc.centroid(d) + ")"; 
            
                }
                      
            })
            .attr("text-anchor", "middle") 
            .text(function(d, i) { 
              
              return data[i].percent + '%';
               
              
            });
            

var labels = g.append('g').classed('labels', true);

labels.selectAll("text").data(piedata)
    .enter()
    .append("text")
    .attr("text-anchor", "middle")
    .attr("x", function(d) {
        var a = d.startAngle + (d.endAngle - d.startAngle)/2 - Math.PI/2;
        d.cx = Math.cos(a) * (radius - 75);
        return d.x = Math.cos(a) * (radius - 20);
    })
    .attr("y", function(d) {
        var a = d.startAngle + (d.endAngle - d.startAngle)/2 - Math.PI/2;
        d.cy = Math.sin(a) * (radius - 75);
        return d.y = Math.sin(a) * (radius - 20);
    })
    .text(function(d) { return d.data.label; })
    .each(function(d) {
        var bbox = this.getBBox();
        d.sx = d.x - bbox.width/2 - 2;
        d.ox = d.x + bbox.width/2 + 2;
        d.sy = d.oy = d.y + 5;
    });

/* labels.append("defs").append("marker")
    .attr("id", "circ")
    .attr("markerWidth", 6)
    .attr("markerHeight", 6)
    .attr("refX", 3)
    .attr("refY", 3)
    .append("circle")
    .attr("cx", 3)
    .attr("cy", 3)
    .attr("r", 3); */

labels.selectAll("path.pointer").data(piedata).enter()
    .append("path")
    .attr("class", "pointer")
    .style("fill", "none")
    .style("stroke", "black")
    .attr("marker-end", "url(#circ)")
    .attr("d", function(d) {
        if(d.cx > d.ox) {
            return "M" + d.sx + "," + d.sy + "L" + d.ox + "," + d.oy + " " + d.cx + "," + d.cy;
        } else {
            return "M" + d.ox + "," + d.oy + "L" + d.sx + "," + d.sy + " " + d.cx + "," + d.cy;
        }
    });
body {
    font: 10px sans-serif;
}
.arc path {
    stroke: #fff;
}
text {
    font-size:12px
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.3.0/d3.min.js"></script>
<div id="donut"></div>

  1. 代码也由标记组成(我现在评论过)。如果那是你不介意的补充,请尝试取消注释。
  2. 根据需要设置连接器的样式。
  3. 希望这会有所帮助。