d3js与节点,如何在饼图中添加一行?

时间:2016-06-17 18:54:33

标签: javascript node.js d3.js svg datejs

d3js新手在这里。我正在使用d3js在服务器上呈现svg。在阅读了一些教程之后,我能够想出这个:

private

虽然这会渲染SVG图表,但我不知道如何在图表中添加行,这将显示哪个切片属于哪个类别。

我该怎么做?

1 个答案:

答案 0 :(得分:1)

编辑/更新(注意:由' 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>
&#13;
&#13;
&#13;

你的意思是这样吗?

&#13;
&#13;
var w = 400;
var h = 400;
var r = h / 2;
var color = d3.scale.category20c();

var data = [{
  "label": "Category A",
  "value": 20
}, {
  "label": "Category B",
  "value": 50
}, {
  "label": "Category C",
  "value": 30
}];


var vis = d3.select('#pie').append("svg:svg").data([data]).attr("width", w).attr("height", h).append("svg:g").attr("transform", "translate(" + r + "," + r + ")");
var pie = d3.layout.pie().value(function(d) {
  return d.value;
});
var arc = d3.svg.arc().outerRadius(r);
var arcs = vis.selectAll("g.slice").data(pie).enter().append("svg:g").attr("class", "slice");
arcs.append("svg:path")
  .attr("fill", function(d, i) {
    return color(i);
  })
  .attr("d", function(d) {
    return arc(d);
  });

// add the text
arcs.append("svg:text").attr("transform", function(d) {
  d.innerRadius = 0;
  d.outerRadius = r;
  return "translate(" + arc.centroid(d) + ")";
}).attr("text-anchor", "middle").text(function(d, i) {
  return data[i].label;
});
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="pie">

</div>
&#13;
&#13;
&#13;