d3js与节点,如何添加一条线到饼图?

d3js新手在这里。 我正在使用d3js在服务器上呈现一个SVG。 经过一些教程,我能够想出这个:

var fs = require('fs'); var d3 = require('d3'); var jsdom = require('jsdom'); var _ = require("underscore"); var chartWidth = 500, chartHeight = 500; var arc = d3.svg.arc() .outerRadius(chartWidth/2 - 10) .innerRadius(0); var colours = ['#98abc5','#8a89a6','#7b6888','#6b486b','#a05d56',"#d0743c", "#ff8c00"]; var pieData = [ { "category" : "Category A", "amount" : 300 }, { "category" : "Category B", "amount" : 300 } ]; makePie( pieData ); function makePie( pieData, outputLocation ){ var amount = _.pluck( pieData, "amount" ); var category = _.pluck( pieData, "category" ); jsdom.env({ html:'', features:{ QuerySelector:true }, //you need query selector for D3 to work done:function(errors, window){ window.d3 = d3.select(window.document); //get d3 into the dom //do yr normal d3 stuff var svg = window.d3.select('body') .append('div') .attr('class','container') //make a container div to ease the saving process .append('svg') .attr({ xmlns:'http://www.w3.org/2000/svg', width:chartWidth, height:chartHeight }) .append('g') .attr('transform','translate(' + chartWidth/2 + ',' + chartWidth/2 + ')'); svg.selectAll('.arc') .data( d3.layout.pie()(amount) ) .enter() .append('path') .attr({ 'class':'arc', 'd':arc, 'fill':function(d,i){ return colours[i]; }, 'stroke':'#fff' }); //write out the children of the container div fs.writeFileSync("test.svg", window.d3.select('.container').html()) //using sync to keep the code simple } }); } 

虽然这呈现SVG图表,但我不知道如何在图表中添加线条,以显示哪个片段属于哪个类别。

我怎么做?

编辑/更新(注:由'thudfactor'撰写) – 这是如何添加标签/线条

 var data = [{ label: 'Star Wars', instances: 207 }, { label: 'Lost In Space', instances: 3 }, { label: 'the Boston Pops', instances: 20 }, { label: 'Indiana Jones', instances: 150 }, { label: 'Harry Potter', instances: 75 }, { label: 'Jaws', instances: 5 }, { label: 'Lincoln', instances: 1 }]; svg = d3.select("svg"); canvas = d3.select("#canvas"); art = d3.select("#art"); labels = d3.select("#labels"); // Create the pie layout function. // This function will add convenience // data to our existing data, like // the start angle and end angle // for each data element. jhw_pie = d3.layout.pie() jhw_pie.value(function (d, i) { // Tells the layout function what // property of our data object to // use as the value. return d.instances; }); // Store our chart dimensions cDim = { height: 500, width: 500, innerRadius: 50, outerRadius: 150, labelRadius: 175 } // Set the size of our SVG element svg.attr({ height: cDim.height, width: cDim.width }); // This translate property moves the origin of the group's coordinate // space to the center of the SVG element, saving us translating every // coordinate individually. canvas.attr("transform", "translate(" + (cDim.width / 2) + "," + (cDim.width / 2) + ")"); pied_data = jhw_pie(data); // The pied_arc function we make here will calculate the path // information for each wedge based on the data set. This is // used in the "d" attribute. pied_arc = d3.svg.arc() .innerRadius(50) .outerRadius(150); // This is an ordinal scale that returns 10 predefined colors. // It is part of d3 core. pied_colors = d3.scale.category10(); // Let's start drawing the arcs. enteringArcs = art.selectAll(".wedge").data(pied_data).enter(); enteringArcs.append("path") .attr("class", "wedge") .attr("d", pied_arc) .style("fill", function (d, i) { return pied_colors(i); }); // Now we'll draw our label lines, etc. enteringLabels = labels.selectAll(".label").data(pied_data).enter(); labelGroups = enteringLabels.append("g").attr("class", "label"); labelGroups.append("circle").attr({ x: 0, y: 0, r: 2, fill: "#000", transform: function (d, i) { centroid = pied_arc.centroid(d); return "translate(" + pied_arc.centroid(d) + ")"; }, 'class': "label-circle" }); // "When am I ever going to use this?" I said in // 10th grade trig. textLines = labelGroups.append("line").attr({ x1: function (d, i) { return pied_arc.centroid(d)[0]; }, y1: function (d, i) { return pied_arc.centroid(d)[1]; }, x2: function (d, i) { centroid = pied_arc.centroid(d); midAngle = Math.atan2(centroid[1], centroid[0]); x = Math.cos(midAngle) * cDim.labelRadius; return x; }, y2: function (d, i) { centroid = pied_arc.centroid(d); midAngle = Math.atan2(centroid[1], centroid[0]); y = Math.sin(midAngle) * cDim.labelRadius; return y; }, 'class': "label-line" }); textLabels = labelGroups.append("text").attr({ x: function (d, i) { centroid = pied_arc.centroid(d); midAngle = Math.atan2(centroid[1], centroid[0]); x = Math.cos(midAngle) * cDim.labelRadius; sign = (x > 0) ? 1 : -1 labelX = x + (5 * sign) return labelX; }, y: function (d, i) { centroid = pied_arc.centroid(d); midAngle = Math.atan2(centroid[1], centroid[0]); y = Math.sin(midAngle) * cDim.labelRadius; return y; }, 'text-anchor': function (d, i) { centroid = pied_arc.centroid(d); midAngle = Math.atan2(centroid[1], centroid[0]); x = Math.cos(midAngle) * cDim.labelRadius; return (x > 0) ? "start" : "end"; }, 'class': 'label-text' }).text(function (d) { return d.data.label }); alpha = 0.5; spacing = 12; function relax() { again = false; textLabels.each(function (d, i) { a = this; da = d3.select(a); y1 = da.attr("y"); textLabels.each(function (d, j) { b = this; // a & b are the same element and don't collide. if (a == b) return; db = d3.select(b); // a & b are on opposite sides of the chart and // don't collide if (da.attr("text-anchor") != db.attr("text-anchor")) return; // Now let's calculate the distance between // these elements. y2 = db.attr("y"); deltaY = y1 - y2; // Our spacing is greater than our specified spacing, // so they don't collide. if (Math.abs(deltaY) > spacing) return; // If the labels collide, we'll push each // of the two labels up and down a little bit. again = true; sign = deltaY > 0 ? 1 : -1; adjust = sign * alpha; da.attr("y",+y1 + adjust); db.attr("y",+y2 - adjust); }); }); // Adjust our line leaders here // so that they follow the labels. if(again) { labelElements = textLabels[0]; textLines.attr("y2",function(d,i) { labelForLine = d3.select(labelElements[i]); return labelForLine.attr("y"); }); setTimeout(relax,20) } } relax(); 
 .label-text { alignment-baseline: middle; font-size: 12px; font-family: arial,helvetica,"sans-serif"; fill: #393939; } .label-line { stroke-width: 1; stroke: #393939; } .label-circle { fill: #393939; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> <svg> <g id="canvas"> <g id="art" /> <g id="labels" /></g> </svg>