D3 Donut Chart Enter with Transition - javascript

I have been working from this D3 block http://bl.ocks.org/dbuezas/9306799.
I have the code pretty much the way I want it. Except the chart only animates when part of the data set is shared. If the the dataset contains no labels in common, the graph is simply swapped out. How do I make it do a growing arc transition from the beginning so the user always knows when new data is presented? I am taking this snippet out of an angular directive so it might not stand quite on its own, fyi.
var padding = 0;
var height = 350;
var width = 450;
var svg = d3.select("body")
.append("svg")
.attr('viewBox','0 0 '+ width +' '+ height)
.attr('preserveAspectRatio','xMinYMin')
.append("g")
svg.append("g")
.attr("class", "slices");
svg.append("g")
.attr("class", "labels");
svg.append("g")
.attr("class", "lines");
var radius = Math.min(width, height) / 2;
var pie = d3.layout.pie()
.sort(null)
.value(function(d) {
return d.value;
});
var arc = d3.svg.arc()
.outerRadius(radius * 0.8)
.innerRadius(radius * 0.6);
var outerArc = d3.svg.arc()
.innerRadius(radius * 0.9)
.outerRadius(radius * 0.9);
svg.attr("transform", "translate(" + width / 2 + "," + element.parent().height() / 2 + ")");
var key = function(d){ return d.data.label; };
var color = d3.scale.category20b();
var dataset = [
{
label: "SUPPLY",
percentage: "22",
value: 10621
},
{
label: "FROZEN",
percentage: "22",
value: 17621
}
];
render(dataset);
function render(data) {
/* ------- PIE SLICES -------*/
var slice = svg.select(".slices").selectAll("path.slice")
.data(pie(data), key);
slice.enter()
.insert("path")
.style("fill", function(d) { return color(d.data.label); })
.attr("class", "slice");
slice
.transition().duration(1000)
.attrTween("d", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
return arc(interpolate(t));
};
})
slice.exit()
.remove();
/* ------- TOOLTIP -----------*/
var tooltip = d3.select(element.parent()[0])
.append('div')
.attr('class', 'donut-tip bodhi-tooltip');
tooltip.append('div')
.attr('class', 'bodhi-tooltip-text');
slice.on('mouseover', function(d) {
tooltip.select('.bodhi-tooltip-text').html(d.data.label + '</br>' + d.data[scope.tooltipKeyOne] + "%" + '</br>' + "$" + (d.data.total / 100).toFixed(2));
tooltip.style('display', 'table');
});
slice.on('mouseout', function(d) {
tooltip.style('display', 'none');
});
/* ------- TEXT LABELS -------*/
var text = svg.select(".labels").selectAll("text")
.data(pie(data), key);
text.enter()
.append("text")
.attr("dy", ".35em")
.text(function(d) {
return d.data.label;
});
function midAngle(d){
return d.startAngle + (d.endAngle - d.startAngle)/2;
}
text.transition().duration(1000)
.attrTween("transform", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
var pos = outerArc.centroid(d2);
return "translate("+ pos +")";
};
})
.styleTween("text-anchor", function(d){
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
return midAngle(d2) < Math.PI ? "start":"end";
};
});
text.exit()
.remove();
};

The heart of the problem is there's no starting point for entering slices to tween from. That said, I'd really simplify the tween code a bit:
slice.enter()
.insert("path")
.style("fill", function(d) {
return color(d.data.label);
})
.attr("class", "slice")
.each(function(d){
this._current = { //<-- give the entering slices a starting point
startAngle: d.startAngle, //<-- have them "grow" from nothing
endAngle: d.startAngle
};
});
slice
.transition().duration(1000)
.attrTween("d", function(d) {
var endAt = { //<-- have the arc end where it's supposed to
startAngle: d.startAngle,
endAngle: d.endAngle
};
var interpolate = d3.interpolate(this._current, endAt);
this._current = endAt; //<-- store this for next cycle
return function(t) {
return arc(interpolate(t));
};
})
Full working code:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3#3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>
<body>
<script>
var padding = 0;
var height = 350;
var width = 450;
var svg = d3.select("body")
.append("svg")
.attr('viewBox', '0 0 ' + width + ' ' + height)
.attr('preserveAspectRatio', 'xMinYMin')
.append("g")
svg.append("g")
.attr("class", "slices");
svg.append("g")
.attr("class", "labels");
svg.append("g")
.attr("class", "lines");
var radius = Math.min(width, height) / 2;
var pie = d3.layout.pie()
.sort(null)
.value(function(d) {
return d.value;
});
var arc = d3.svg.arc()
.outerRadius(radius * 0.8)
.innerRadius(radius * 0.6);
var outerArc = d3.svg.arc()
.innerRadius(radius * 0.9)
.outerRadius(radius * 0.9);
svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var key = function(d) {
return d.data.label;
};
var color = d3.scale.category20b();
update();
setInterval(update, 2000);
function update() {
var someData = [];
for (var i = 0; i < Math.random() * 10; i++){
someData.push({
label: "Slice " + i,
percentage: "22",
value: Math.random()
});
}
render(someData);
}
function render(data) {
/* ------- PIE SLICES -------*/
var slice = svg.select(".slices").selectAll("path.slice")
.data(pie(data), key);
slice.enter()
.insert("path")
.style("fill", function(d) {
return color(d.data.label);
})
.attr("class", "slice")
.each(function(d){
this._current = {
startAngle: d.startAngle,
endAngle: d.startAngle
};
});
slice
.transition().duration(1000)
.attrTween("d", function(d) {
var endAt = {
startAngle: d.startAngle,
endAngle: d.endAngle
};
var interpolate = d3.interpolate(this._current, endAt);
this._current = endAt;
return function(t) {
return arc(interpolate(t));
};
})
slice.exit()
.remove();
/* ------- TEXT LABELS -------*/
var text = svg.select(".labels").selectAll("text")
.data(pie(data), key);
text.enter()
.append("text")
.attr("dy", ".35em")
.text(function(d) {
return d.data.label;
});
function midAngle(d) {
return d.startAngle + (d.endAngle - d.startAngle) / 2;
}
text.transition().duration(1000)
.attrTween("transform", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
var pos = outerArc.centroid(d2);
return "translate(" + pos + ")";
};
})
.styleTween("text-anchor", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
return midAngle(d2) < Math.PI ? "start" : "end";
};
});
text.exit()
.remove();
};
</script>
</body>
</html>

Related

How do I draw line from the outer most arc of the circle

I am trying to draw the label line the outer most point of the circle like this picture.
var svg = d3.select("body")
.append("svg")
.append("g")
svg.append("g")
.attr("class", "slices");
svg.append("g")
.attr("class", "labels");
svg.append("g")
.attr("class", "lines");
var width = 960,
height = 450,
radius = Math.min(width, height) / 2;
var pie = d3.layout.pie()
.sort(null)
.value(function(d) {
return d.value;
});
var arc = d3.svg.arc()
.outerRadius(radius * 0.8)
.innerRadius(radius * 0.4);
var outerArc = d3.svg.arc()
.innerRadius(radius * 0.9)
.outerRadius(radius * 0.9);
svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var key = function(d) {
return d.data.label;
};
var color = d3.scale.ordinal()
.domain(["53% KILLED 2791", "dolor sit", "amet", "consectetur", "adipisicing", "elit", "sed", "do", "eiusmod", "tempor", "incididunt"])
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
function randomData() {
var labels = color.domain();
return labels.map(function(label) {
return {
label: label,
value: Math.random()
}
});
}
change(randomData());
d3.select(".randomize")
.on("click", function() {
change(randomData());
});
function change(data) {
/* ------- PIE SLICES -------*/
var slice = svg.select(".slices").selectAll("path.slice")
.data(pie(data), key);
slice.enter()
.insert("path")
.style("fill", function(d) {
return color(d.data.label);
})
.attr("class", "slice");
slice
.transition().duration(1000)
.attrTween("d", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
return arc(interpolate(t));
};
})
slice.exit()
.remove();
/* ------- TEXT LABELS -------*/
var text = svg.select(".labels").selectAll("text")
.data(pie(data), key);
text.enter()
.append("text")
.attr("dy", ".35em")
.text(function(d) {
return d.data.label;
});
function midAngle(d) {
return d.startAngle + (d.endAngle - d.startAngle) / 2;
}
text.transition().duration(1000)
.attrTween("transform", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
var pos = outerArc.centroid(d2);
pos[0] = radius * (midAngle(d2) < Math.PI ? 1 : -1);
return "translate(" + pos + ")";
};
})
.styleTween("text-anchor", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
return midAngle(d2) < Math.PI ? "start" : "end";
};
});
text.exit()
.remove();
/* ------- SLICE TO TEXT POLYLINES -------*/
var polyline = svg.select(".lines").selectAll("polyline")
.data(pie(data), key);
polyline.enter()
.append("polyline");
polyline.transition().duration(1000)
.attrTween("points", function(d){
this._current = this._current || d;
console.log('_current = ' + JSON.stringify(this._current));
console.log('d = ' + JSON.stringify(d));
var interpolate = d3.interpolate(this._current, d);
console.log('interpolate = ' + JSON.stringify(interpolate(0)));
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
console.log('t = ' + JSON.stringify(t));
console.log('d2 = ' + JSON.stringify(d2));
var pos = outerArc.centroid(d2);
pos[0] = radius * 0.95 * (midAngle(d2) < Math.PI ? 1 : -1);
return [arc.centroid(d2), outerArc.centroid(d2), pos];
};
});
polyline.exit()
.remove();
};
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
width: 960px;
height: 500px;
position: relative;
}
svg {
width: 100%;
height: 100%;
}
path.slice {
stroke-width: 2px;
}
polyline {
opacity: .3;
stroke: black;
stroke-width: 2px;
fill: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
<button class="randomize">randomize</button>
I am new to D3 and not too sure how to calculate the points to achieve this. I tried looking up formulas what calculating circles but wasn't sure which formula is best for this situation.
Any help is greatly appreciated.
Based on your code, you can see that the lines connecting the arc segments to the text is drawn by this code (near the end of your snippet):
return [arc.centroid(d2), outerArc.centroid(d2), pos];
It basically draws:
from the center of the segment, arc.centroid(d2) (which is drawn between the 0.4 to 0.8 of the radius)
makes a stop at the virtual outer arc, outerArc.centroid(d2) (which is drawn at 0.9) of the radius: this is where the line bends
and finally ends at pos where the text label is anchored at
So, if you want it to start outside the main pie chart, simply supply a new arc to the first argument. Let's give that arc a radius of 0.82, for example:
var polylineStartArc = d3.svg.arc()
.innerRadius(radius * 0.82)
.outerRadius(radius * 0.82);
And then you ammend your polyline drawing logic with this:
return [polylineStartArc.centroid(d2), outerArc.centroid(d2), pos];
Of course, you can adjust this value between the range of 0.8 and 0.9:
you want to keep it >0.8 so that it does not intersect with the pie chart
you want to keep it <0.9 so that it does not go further out than the "bend" in the line
See proof-of-concept below:
var svg = d3.select("body")
.append("svg")
.append("g")
svg.append("g")
.attr("class", "slices");
svg.append("g")
.attr("class", "labels");
svg.append("g")
.attr("class", "lines");
var width = 960,
height = 450,
radius = Math.min(width, height) / 2;
var pie = d3.layout.pie()
.sort(null)
.value(function(d) {
return d.value;
});
var arc = d3.svg.arc()
.outerRadius(radius * 0.8)
.innerRadius(radius * 0.4);
var outerArc = d3.svg.arc()
.innerRadius(radius * 0.9)
.outerRadius(radius * 0.9);
var polylineStartArc = d3.svg.arc()
.innerRadius(radius * 0.82)
.outerRadius(radius * 0.82);
svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var key = function(d) {
return d.data.label;
};
var color = d3.scale.ordinal()
.domain(["53% KILLED 2791", "dolor sit", "amet", "consectetur", "adipisicing", "elit", "sed", "do", "eiusmod", "tempor", "incididunt"])
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
function randomData() {
var labels = color.domain();
return labels.map(function(label) {
return {
label: label,
value: Math.random()
}
});
}
change(randomData());
d3.select(".randomize")
.on("click", function() {
change(randomData());
});
function change(data) {
/* ------- PIE SLICES -------*/
var slice = svg.select(".slices").selectAll("path.slice")
.data(pie(data), key);
slice.enter()
.insert("path")
.style("fill", function(d) {
return color(d.data.label);
})
.attr("class", "slice");
slice
.transition().duration(1000)
.attrTween("d", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
return arc(interpolate(t));
};
})
slice.exit()
.remove();
/* ------- TEXT LABELS -------*/
var text = svg.select(".labels").selectAll("text")
.data(pie(data), key);
text.enter()
.append("text")
.attr("dy", ".35em")
.text(function(d) {
return d.data.label;
});
function midAngle(d) {
return d.startAngle + (d.endAngle - d.startAngle) / 2;
}
text.transition().duration(1000)
.attrTween("transform", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
var pos = outerArc.centroid(d2);
pos[0] = radius * (midAngle(d2) < Math.PI ? 1 : -1);
return "translate(" + pos + ")";
};
})
.styleTween("text-anchor", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
return midAngle(d2) < Math.PI ? "start" : "end";
};
});
text.exit()
.remove();
/* ------- SLICE TO TEXT POLYLINES -------*/
var polyline = svg.select(".lines").selectAll("polyline")
.data(pie(data), key);
polyline.enter()
.append("polyline");
polyline.transition().duration(1000)
.attrTween("points", function(d){
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
var pos = outerArc.centroid(d2);
pos[0] = radius * 0.95 * (midAngle(d2) < Math.PI ? 1 : -1);
return [polylineStartArc.centroid(d2), outerArc.centroid(d2), pos];
};
});
polyline.exit()
.remove();
};
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
width: 960px;
height: 500px;
position: relative;
}
svg {
width: 100%;
height: 100%;
}
path.slice {
stroke-width: 2px;
}
polyline {
opacity: .3;
stroke: black;
stroke-width: 2px;
fill: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
<button class="randomize">randomize</button>

D3 v4 - Pie Chart with connectors outside the pie and with dots.

I am trying to change the following example i started out with to edit the lines such that they
start 5px outside the center of the slice
have a 4px circle around
The design is as follows. The main part im struggling with initially is changing the starting point. I think the circle will be easy if i can figure that out.
Any suggestions how to achieve this?
var svg = d3.select("body")
.append("svg")
.append("g")
var isDount = false;
svg.append("g")
.attr("class", "slices");
svg.append("g")
.attr("class", "labels");
svg.append("g")
.attr("class", "lines");
var width = 200,
height = 200,
radius = Math.min(width, height) / 2,
transitionSpeed = 600;
var pie = d3.pie()
.sort(null)
.value(function(d) {
return d.value;
});
var arc = d3.arc()
.outerRadius(radius * 0.8)
.innerRadius(isDount ? radius * 0.4 : 0);
var outerArc = d3.arc()
.innerRadius(radius * 0.9)
.outerRadius(isDount ? radius * 0.9 : 0);
svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var key = function(d) {
return d.data.label;
};
var color = d3.scaleOrdinal()
.domain(["Lorem ipsum", "dolor sit", "amet", "consectetur"]) //, "adipisicing", "elit", "sed", "do", "eiusmod", "tempor", "incididunt"
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
function randomData() {
var labels = color.domain();
return labels.map(function(label) {
return {
label: label,
value: Math.random()
}
});
}
change(randomData());
d3.select(".randomize")
.on("click", function() {
change(randomData());
});
function change(data) {
/* ------- PIE SLICES -------*/
var slice = svg.select(".slices").selectAll("path.slice")
.data(pie(data), key);
slice.enter()
.insert("path")
.style("fill", function(d) {
return color(d.data.label);
})
.attr("class", "slice")
.merge(slice)
.transition().duration(transitionSpeed)
.attrTween("d", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
return arc(interpolate(t));
};
})
slice.exit()
.remove();
/* ------- TEXT LABELS -------*/
var text = svg.select(".labels").selectAll("text")
.data(pie(data), key);
function midAngle(d) {
return d.startAngle + (d.endAngle - d.startAngle) / 2;
}
text.enter()
.append("text")
.attr("dy", ".35em")
.text(function(d) {
console.log(d3.format('.3f')(d.data.value))
var showValue = true;
return showValue ? d3.format('.3f')(d.data.value) : d.data.label;
})
.merge(text)
.transition().duration(transitionSpeed)
.attrTween("transform", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
var pos = outerArc.centroid(d2);
pos[0] = radius * (midAngle(d2) < Math.PI ? 1 : -1);
return "translate(" + pos + ")";
};
})
.styleTween("text-anchor", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
return midAngle(d2) < Math.PI ? "start" : "end";
};
});
text.exit()
.remove();
/* ------- SLICE TO TEXT POLYLINES -------*/
var polyline = svg.select(".lines").selectAll("polyline")
.data(pie(data), key);
polyline.enter()
.append("polyline")
.merge(polyline)
.transition().duration(transitionSpeed)
.attrTween("points", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
var pos = outerArc.centroid(d2);
pos[0] = radius * 0.95 * (midAngle(d2) < Math.PI ? 1 : -1);
return [arc.centroid(d2), outerArc.centroid(d2), pos];
};
});
polyline.exit()
.remove();
};
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
width: 960px;
height: 500px;
position: relative;
}
svg {
width: 100%;
height: 100%;
}
path.slice {
stroke-width: 2px;
}
polyline {
opacity: .3;
stroke: black;
stroke-width: 1px;
fill: none;
}
.labels text {
font-size: 12px;
}
<button class="randomize">c</button>
<script src="http://d3js.org/d3.v4.min.js"></script>
You could make a new arc variable and change the innerradius to a higher value. for example
var arc2 = d3.arc()
.outerRadius(radius * 0.8 -10)
.innerRadius(isDount ? radius * 0.4 : 0);
and reference it in the attrTween & mess around with the values
return [arc2.centroid(d2), outerArc.centroid(d2), pos];
I also added the circles the way you wanted:
var circles = svg.selectAll(".circles")
.data(pie(data));
circles = circles.enter()
.append("circle")
.attr("class","circles")
.attr("r",3)
.attr("fill","#999")
.merge(circles)
circles.transition().duration(transitionSpeed)
.attrTween("transform", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
var pos = outerArc.centroid(d2);
pos[0] = radius * .95 * (midAngle(d2) < Math.PI ? 1 : -1);
return "translate("+ circlesArc.centroid(d2) +")";
};
})
circles.exit().remove();
Here's a fork:
var svg = d3.select("body")
.append("svg")
.append("g")
var isDount = false;
svg.append("g")
.attr("class", "slices");
svg.append("g")
.attr("class", "labels");
svg.append("g")
.attr("class", "lines");
var width = 200,
height = 200,
radius = Math.min(width, height) / 2,
transitionSpeed = 600,
outerRadius = height / 2 - 20;
var pie = d3.pie()
.sort(null)
.value(function(d) {
return d.value;
});
var arc = d3.arc()
.outerRadius(radius * 0.8 -10)
.innerRadius(isDount ? radius * 0.4 : 0);
var arc2 = d3.arc()
.outerRadius(radius * 0.8 -10)
.innerRadius(radius * 0.9)
var outerArc = d3.arc()
.innerRadius(radius * .99)
.outerRadius(radius * .99);
var circlesArc = d3.arc()
.innerRadius(radius * 0.8)
.outerRadius(radius * 0.8);
svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var key = function(d) {
return d.data.label;
};
var color = d3.scaleOrdinal()
.domain(["Lorem ipsum", "dolor sit", "amet", "consectetur"]) //, "adipisicing", "elit", "sed", "do", "eiusmod", "tempor", "incididunt"
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
function randomData() {
var labels = color.domain();
return labels.map(function(label) {
return {
label: label,
value: Math.random()
}
});
}
change(randomData());
d3.select(".randomize")
.on("click", function() {
change(randomData());
});
function change(data) {
/* ------- PIE SLICES -------*/
var slice = svg.select(".slices").selectAll("path.slice")
.data(pie(data), key);
slice.enter()
.insert("path")
.style("fill", function(d) {
return color(d.data.label);
})
.attr("class", "slice")
.merge(slice)
.transition().duration(transitionSpeed)
.attrTween("d", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
return arc(interpolate(t));
};
})
slice.exit()
.remove();
/* ------- TEXT LABELS -------*/
var text = svg.select(".labels").selectAll("text")
.data(pie(data), key);
function midAngle(d) {
return d.startAngle + (d.endAngle - d.startAngle) / 2;
}
text.enter()
.append("text")
.attr("dy", ".35em")
.text(function(d) {
console.log(d3.format('.3f')(d.data.value))
var showValue = true;
return showValue ? d3.format('.3f')(d.data.value) : d.data.label;
})
.merge(text)
.transition().duration(transitionSpeed)
.attrTween("transform", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
var pos = outerArc.centroid(d2);
pos[0] = radius * (midAngle(d2) < Math.PI ? 1 : -1);
return "translate(" + pos + ")";
};
})
.styleTween("text-anchor", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
return midAngle(d2) < Math.PI ? "start" : "end";
};
});
text.exit()
.remove();
/* ------- SLICE TO TEXT POLYLINES -------*/
var polyline = svg.select(".lines").selectAll("polyline")
.data(pie(data), key);
polyline.enter()
.append("polyline")
.merge(polyline)
.transition().duration(transitionSpeed)
.attrTween("points", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
var pos = outerArc.centroid(d2);
pos[0] = radius * 0.95 * (midAngle(d2) < Math.PI ? 1 : -1);
return [arc2.centroid(d2), outerArc.centroid(d2), pos];
};
});
polyline.exit()
.remove();
var circles = svg.selectAll(".circles")
.data(pie(data));
circles = circles.enter()
.append("circle")
.attr("class","circles")
.attr("r",3)
.attr("fill","#999")
.merge(circles)
circles.transition().duration(transitionSpeed)
.attrTween("transform", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
var pos = outerArc.centroid(d2);
pos[0] = radius * .95 * (midAngle(d2) < Math.PI ? 1 : -1);
return "translate("+ circlesArc.centroid(d2) +")";
};
})
circles.exit().remove();
};
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
width: 960px;
height: 500px;
position: relative;
}
svg {
width: 100%;
height: 100%;
}
path.slice {
stroke-width: 2px;
}
polyline {
opacity: .3;
stroke: black;
stroke-width: 1px;
fill: none;
}
.labels text {
font-size: 12px;
}
<button class="randomize">c</button>
<script src="https://d3js.org/d3.v4.min.js"></script>

d3js write labels on multiline

I'm working on graphics and I met some difficulties on charts. I want to draw a pie chart (or donut) and to display labels in two lines or more in order to get the more space for the graph.
Here is my code
var dataGroupPotential = [];
var pieGroup;
var svg;
processData("pieGPChart");
function processData(chartDivId) {
$("#pieGPLegend").text("Title : myTitle");
//Construction du tableau data
dataGroupPotential.push({
label: "long text 1 : 100 000 000",
value: 100000000
});
dataGroupPotential.push({
label: "long text 2 : 200 000 000",
value: 200000000
});
dataGroupPotential.push({
label: "long text 3 : 300 000 000",
value: 300000000
});
var width = $("#" + chartDivId).width();
var dividor = 2.75;
var height = width / dividor;
//Ajout des éléments svg pour tracer le graphique
svg = d3.select("#" + chartDivId).append("svg")
.attr("width", '100%')
.attr("height", '100%')
.attr('viewBox', '0 0 ' + Math.min(width, height) + ' ' + Math.min(width, height))
.attr('preserveAspectRatio', 'xMinYMin')
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");;
svg.append("g").attr("class", "slices");
svg.append("g").attr("class", "labels");
svg.append("g").attr("class", "lines");
$("#" + chartDivId).height(height);
drawMyPie(svg, dataGroupPotential, width, height);
window.addEventListener('resize', function(event) {
// do stuff here
var chartDivId = "pieGPChart";
var width = $("#" + chartDivId).width();
var dividor = 2.75;
var height = width / dividor;
$("#" + chartDivId).height(height);
drawMyPie(svg, dataGroupPotential, width, height);
});
}
function drawMyPie(svg, data, width, height) {
var radius = Math.min(width, height) / 2;
var pie = d3.pie()
.sort(null)
.value(function(d) {
return d.value;
});
var arc = d3.arc()
.outerRadius(radius * 0.8)
.innerRadius(radius * 0.4);
var outerArc = d3.arc()
.innerRadius(radius * 0.9)
.outerRadius(radius * 0.9);
//svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var key = function(d) {
return d.data.label;
};
var color = d3.scaleOrdinal(d3.schemeCategory20);
change(data);
function mergeWithFirstEqualZero(first, second) {
var secondSet = d3.set();
second.forEach(function(d) {
secondSet.add(d.label);
});
var onlyFirst = first
.filter(function(d) {
return !secondSet.has(d.label)
})
.map(function(d) {
return {
label: d.label,
value: 0
};
});
return d3.merge([second, onlyFirst])
.sort(function(a, b) {
return d3.ascending(a.label, b.label);
});
}
function change(data) {
var duration = 3000;
var data0 = svg.select(".slices").selectAll("path.slice")
.data().map(function(d) {
return d.data
});
if (data0.length == 0) data0 = data;
var was = mergeWithFirstEqualZero(data, data0);
var is = mergeWithFirstEqualZero(data0, data);
/* ------- SLICE ARCS -------*/
var slice = svg.select(".slices").selectAll("path.slice")
.data(pie(was), key);
slice.enter()
.insert("path")
.attr("class", "slice")
.style("fill", function(d) {
return color(d.data.label);
})
.each(function(d) {
this._current = d;
});
slice = svg.select(".slices").selectAll("path.slice")
.data(pie(is), key);
slice
.transition().duration(duration)
.attrTween("d", function(d) {
var interpolate = d3.interpolate(this._current, d);
var _this = this;
return function(t) {
_this._current = interpolate(t);
return arc(_this._current);
};
});
slice = svg.select(".slices").selectAll("path.slice")
.data(pie(data), key);
slice
.exit().transition().delay(duration).duration(0)
.remove();
/* ------- TEXT LABELS -------*/
var text = svg.select(".labels").selectAll("text")
.data(pie(was), key);
text.enter()
.append("text")
.attr("dy", ".35em")
.style("opacity", 0)
.text(function(d) {
return d.data.label;
})
.each(function(d) {
this._current = d;
});
//var legend = text.enter();
//text.append("text")
// .attr("dy", "-10")
// .style("opacity", 0)
// .text(function (d) {
// return d.data.label;
// })
//.each(function (d) {
// this._current = d;
//});
//text.append("text")
// .attr("dy", "10")
// .style("opacity", 0)
// .text(function (d) {
// return d.data.label;
// })
//.each(function (d) {
// this._current = d;
//});
function midAngle(d) {
return d.startAngle + (d.endAngle - d.startAngle) / 2;
}
text = svg.select(".labels").selectAll("text")
.data(pie(is), key);
text.transition().duration(duration)
.style("opacity", function(d) {
return d.data.value == 0 ? 0 : 1;
})
.attrTween("transform", function(d) {
var interpolate = d3.interpolate(this._current, d);
var _this = this;
return function(t) {
var d2 = interpolate(t);
_this._current = d2;
var pos = outerArc.centroid(d2);
pos[0] = radius * (midAngle(d2) < Math.PI ? 1 : -1);
return "translate(" + pos + ")";
};
})
.styleTween("text-anchor", function(d) {
var interpolate = d3.interpolate(this._current, d);
return function(t) {
var d2 = interpolate(t);
return midAngle(d2) < Math.PI ? "start" : "end";
};
});
text = svg.select(".labels").selectAll("text")
.data(pie(data), key);
text
.exit().transition().delay(duration)
.remove();
/* ------- SLICE TO TEXT POLYLINES -------*/
var polyline = svg.select(".lines").selectAll("polyline")
.data(pie(was), key);
polyline.enter()
.append("polyline")
.style("opacity", 0)
.each(function(d) {
this._current = d;
});
polyline = svg.select(".lines").selectAll("polyline")
.data(pie(is), key);
polyline.transition().duration(duration)
.style("opacity", function(d) {
return d.data.value == 0 ? 0 : .5;
})
.attrTween("points", function(d) {
this._current = this._current;
var interpolate = d3.interpolate(this._current, d);
var _this = this;
return function(t) {
var d2 = interpolate(t);
_this._current = d2;
var pos = outerArc.centroid(d2);
pos[0] = radius * 0.95 * (midAngle(d2) < Math.PI ? 1 : -1);
return [arc.centroid(d2), outerArc.centroid(d2), pos];
};
});
polyline = svg.select(".lines").selectAll("polyline")
.data(pie(data), key);
polyline
.exit().transition().delay(duration)
.remove();
};
}
svg {
width: 100%;
height: 100%;
}
path.slice {
stroke-width: 2px;
}
polyline {
opacity: .3;
stroke: black;
stroke-width: 2px;
fill: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.js"></script>
<div class="panel panel-default">
<div class="panel-body">
<div style="text-align:center;" class="row">
<h4 id="pieGPLegend"></h4>
<div id="pieGPChart"></div>
</div>
</div>
</div>
For the label, I would like to have something like that
long text 1
100 000 000
I already try some stuff, but didn't work. Here is what I try but I'm still confusing with d3js
var legend = text.enter();
text.append("text")
.attr("dy", "-10")
.style("opacity", 0)
.text(function (d) {
return d.data.label;
})
.each(function (d) {
this._current = d;
});
text.append("text")
.attr("dy", "10")
.style("opacity", 0)
.text(function (d) {
return d.data.label;
})
.each(function (d) {
this._current = d;
});
any help, advice, comment is welcome ! thank you
Damien
If you want to always break your text after the colon, the easiest approach is using a <tspan>:
.append("tspan")
.attr("x", 0)
.attr("dy", "1.3em")
.text(function(d) {
return d.data.label.split(":")[1];
})
Here is your code with that change:
var dataGroupPotential = [];
var pieGroup;
var svg;
processData("pieGPChart");
function processData(chartDivId) {
$("#pieGPLegend").text("Title : myTitle");
//Construction du tableau data
dataGroupPotential.push({
label: "long text 1 : 100 000 000",
value: 100000000
});
dataGroupPotential.push({
label: "long text 2 : 200 000 000",
value: 200000000
});
dataGroupPotential.push({
label: "long text 3 : 300 000 000",
value: 300000000
});
var width = $("#" + chartDivId).width();
var dividor = 2.75;
var height = width / dividor;
//Ajout des éléments svg pour tracer le graphique
svg = d3.select("#" + chartDivId).append("svg")
.attr("width", '100%')
.attr("height", '100%')
.attr('viewBox', '0 0 ' + Math.min(width, height) + ' ' + Math.min(width, height))
.attr('preserveAspectRatio', 'xMinYMin')
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");;
svg.append("g").attr("class", "slices");
svg.append("g").attr("class", "labels");
svg.append("g").attr("class", "lines");
$("#" + chartDivId).height(height);
drawMyPie(svg, dataGroupPotential, width, height);
window.addEventListener('resize', function(event) {
// do stuff here
var chartDivId = "pieGPChart";
var width = $("#" + chartDivId).width();
var dividor = 2.75;
var height = width / dividor;
$("#" + chartDivId).height(height);
drawMyPie(svg, dataGroupPotential, width, height);
});
}
function drawMyPie(svg, data, width, height) {
var radius = Math.min(width, height) / 2;
var pie = d3.pie()
.sort(null)
.value(function(d) {
return d.value;
});
var arc = d3.arc()
.outerRadius(radius * 0.8)
.innerRadius(radius * 0.4);
var outerArc = d3.arc()
.innerRadius(radius * 0.9)
.outerRadius(radius * 0.9);
//svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var key = function(d) {
return d.data.label;
};
var color = d3.scaleOrdinal(d3.schemeCategory20);
change(data);
function mergeWithFirstEqualZero(first, second) {
var secondSet = d3.set();
second.forEach(function(d) {
secondSet.add(d.label);
});
var onlyFirst = first
.filter(function(d) {
return !secondSet.has(d.label)
})
.map(function(d) {
return {
label: d.label,
value: 0
};
});
return d3.merge([second, onlyFirst])
.sort(function(a, b) {
return d3.ascending(a.label, b.label);
});
}
function change(data) {
var duration = 3000;
var data0 = svg.select(".slices").selectAll("path.slice")
.data().map(function(d) {
return d.data
});
if (data0.length == 0) data0 = data;
var was = mergeWithFirstEqualZero(data, data0);
var is = mergeWithFirstEqualZero(data0, data);
/* ------- SLICE ARCS -------*/
var slice = svg.select(".slices").selectAll("path.slice")
.data(pie(was), key);
slice.enter()
.insert("path")
.attr("class", "slice")
.style("fill", function(d) {
return color(d.data.label);
})
.each(function(d) {
this._current = d;
});
slice = svg.select(".slices").selectAll("path.slice")
.data(pie(is), key);
slice
.transition().duration(duration)
.attrTween("d", function(d) {
var interpolate = d3.interpolate(this._current, d);
var _this = this;
return function(t) {
_this._current = interpolate(t);
return arc(_this._current);
};
});
slice = svg.select(".slices").selectAll("path.slice")
.data(pie(data), key);
slice
.exit().transition().delay(duration).duration(0)
.remove();
/* ------- TEXT LABELS -------*/
var text = svg.select(".labels").selectAll("text")
.data(pie(was), key);
text.enter()
.append("text")
.attr("dy", ".35em")
.style("opacity", 0)
.text(function(d) {
return d.data.label.split(":")[0] + ":";
})
.each(function(d) {
this._current = d;
})
.append("tspan")
.attr("x", 0)
.attr("dy", "1.3em")
.text(function(d) {
return d.data.label.split(":")[1];
})
.each(function(d) {
this._current = d;
});
//var legend = text.enter();
//text.append("text")
// .attr("dy", "-10")
// .style("opacity", 0)
// .text(function (d) {
// return d.data.label;
// })
//.each(function (d) {
// this._current = d;
//});
//text.append("text")
// .attr("dy", "10")
// .style("opacity", 0)
// .text(function (d) {
// return d.data.label;
// })
//.each(function (d) {
// this._current = d;
//});
function midAngle(d) {
return d.startAngle + (d.endAngle - d.startAngle) / 2;
}
text = svg.select(".labels").selectAll("text")
.data(pie(is), key);
text.transition().duration(duration)
.style("opacity", function(d) {
return d.data.value == 0 ? 0 : 1;
})
.attrTween("transform", function(d) {
var interpolate = d3.interpolate(this._current, d);
var _this = this;
return function(t) {
var d2 = interpolate(t);
_this._current = d2;
var pos = outerArc.centroid(d2);
pos[0] = radius * (midAngle(d2) < Math.PI ? 1 : -1);
return "translate(" + pos + ")";
};
})
.styleTween("text-anchor", function(d) {
var interpolate = d3.interpolate(this._current, d);
return function(t) {
var d2 = interpolate(t);
return midAngle(d2) < Math.PI ? "start" : "end";
};
});
text = svg.select(".labels").selectAll("text")
.data(pie(data), key);
text
.exit().transition().delay(duration)
.remove();
/* ------- SLICE TO TEXT POLYLINES -------*/
var polyline = svg.select(".lines").selectAll("polyline")
.data(pie(was), key);
polyline.enter()
.append("polyline")
.style("opacity", 0)
.each(function(d) {
this._current = d;
});
polyline = svg.select(".lines").selectAll("polyline")
.data(pie(is), key);
polyline.transition().duration(duration)
.style("opacity", function(d) {
return d.data.value == 0 ? 0 : .5;
})
.attrTween("points", function(d) {
this._current = this._current;
var interpolate = d3.interpolate(this._current, d);
var _this = this;
return function(t) {
var d2 = interpolate(t);
_this._current = d2;
var pos = outerArc.centroid(d2);
pos[0] = radius * 0.95 * (midAngle(d2) < Math.PI ? 1 : -1);
return [arc.centroid(d2), outerArc.centroid(d2), pos];
};
});
polyline = svg.select(".lines").selectAll("polyline")
.data(pie(data), key);
polyline
.exit().transition().delay(duration)
.remove();
};
}
svg {
width: 100%;
height: 100%;
}
path.slice {
stroke-width: 2px;
}
polyline {
opacity: .3;
stroke: black;
stroke-width: 2px;
fill: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.js"></script>
<div class="panel panel-default">
<div class="panel-body">
<div style="text-align:center;" class="row">
<h4 id="pieGPLegend"></h4>
<div id="pieGPChart"></div>
</div>
</div>
</div>

How to display labels in pie transition chart using d3.js?

I am using pie transition chart of d3.js to visualize the potential customers.
The graph is drawn, but the labels are not displayed on the graph.
Here is the code:
var w = 400,
h = 400,
r = Math.min(w, h) / 2,
data = [25,45], // Data values
color = d3.scale.category20(),
arc = d3.svg.arc().outerRadius(r),
donut = d3.layout.pie();
var vis = d3.select("#pie-chart-div").append("svg") // Place the chart in 'pie-chart-div'
.data([data])
.attr("width", w)
.attr("height", h);
var arcs = vis.selectAll("g.arc")
.data(donut)
.enter().append("g")
.attr("class", "arc")
.attr("transform", "translate(" + r + "," + r + ")");
var paths = arcs.append("path")
.attr("fill", function(d, i) { return color(i); });
paths.transition()
.ease("bounce")
.duration(2000)
.attrTween("d", tweenPie);
paths.transition()
.ease("elastic")
.delay(function(d, i) { return 2000 + i * 50; })
.duration(750)
.attrTween("d", tweenDonut);
function tweenPie(b) {
b.innerRadius = 0;
var i = d3.interpolate({startAngle: 0, endAngle: 0}, b);
return function(t) {
return arc(i(t));
};
}
function tweenDonut(b) {
b.innerRadius = r * .6;
var i = d3.interpolate({innerRadius: 0}, b);
return function(t) {
return arc(i(t));
};
}
How to display labels in the pie transition chart ?
To display the text in the "exact location" (which I supposed is in the middle of the arc), you can use the centroid() function:
var labels = arcs.append("text")
.attr("transform", function(d) {
d.innerRadius = 120;
return "translate(" + arc.centroid(d) + ")";
})
.attr("dy", ".35em")
.text(function(d) { return d.value; });
Check this demo:
var w = 400,
h = 400,
r = Math.min(w, h) / 2,
data = [25,45], // Data values
color = d3.scale.category20(),
arc = d3.svg.arc().outerRadius(r),
donut = d3.layout.pie();
var vis = d3.select("body").append("svg") // Place the chart in 'pie-chart-div'
.data([data])
.attr("width", w)
.attr("height", h);
var arcs = vis.selectAll("g.arc")
.data(donut)
.enter().append("g")
.attr("class", "arc")
.attr("transform", "translate(" + r + "," + r + ")");
var paths = arcs.append("path")
.attr("fill", function(d, i) { return color(i); });
var labels = arcs.append("text")
.attr("transform", function(d) { d.innerRadius = 120; return "translate(" + arc.centroid(d) + ")"; })
.attr("dy", ".35em")
.text(function(d) { return d.value; });
paths.transition()
.ease("bounce")
.duration(2000)
.attrTween("d", tweenPie);
paths.transition()
.ease("elastic")
.delay(function(d, i) { return 2000 + i * 50; })
.duration(750)
.attrTween("d", tweenDonut);
function tweenPie(b) {
b.innerRadius = 0;
var i = d3.interpolate({startAngle: 0, endAngle: 0}, b);
return function(t) {
return arc(i(t));
};
}
function tweenDonut(b) {
b.innerRadius = r * .6;
var i = d3.interpolate({innerRadius: 0}, b);
return function(t) {
return arc(i(t));
};
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

Javascript array filter | Custom method

I have a problem. Look at the picture below.
The data for my pie is:
var data = [{statusid:"Paid", price:10},
{statusid:"Not accepted", price:20},
{statusid:"Canceled", price:20},
{statusid:"Waiting", price:1},
{statusid:"Refunded", price:1},
{statusid:"Pending", price:1}];
Is it possible to solve this problem by sorting input data? How?
Thanks!
P.S: D3.js code below:
var data = [{statusid:"Paid", price:10}, {statusid:"Not accepted", price:20}, {statusid:"Canceled", price:20}, {statusid:"Waiting", price:1}, {statusid:"Refunded", price:1}, {statusid:"Pending", price:1}];
var sumprice = 0;
for (var i in data) {
sumprice += data[i].price;
}
/* ==============================================================
Setting up the chart
============================================================== */
var width = 600,
height = 500,
radius = Math.min(width, height) / 4;
var color = d3.scale.ordinal()
.range(["#227fbc", "#64a620", "#7b6888", "#a15c57", "#961819", "#d8d13a", "#d3723b"]);
var arc = d3.svg.arc()
.outerRadius(radius * 0.8)
.innerRadius(radius * 0.4);
var outerArc = d3.svg.arc()
.innerRadius(radius * 0.9)
.outerRadius(radius * 0.9);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d.price; });
/* ==============================================================
Creating the svg element
============================================================== */
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
svg.append("g")
.attr("class", "lines");
svg.append("g")
.attr("class", "labels");
/* ==============================================================
Drawning the pizza
============================================================== */
var g = svg.selectAll(".arc")
.data(pie(data))
.enter().append("g")
.attr("class", "arc");
g.append("path")
.attr("d", arc)
.style("fill", function(d) {
return color(d.data.statusid);
});
/* ==============================================================
Drawning the labels
============================================================== */
var key = function(d){ return d.data.statusid; };
var text = svg.select(".labels").selectAll("text")
.data(pie(data), key);
text.enter()
.append("text")
.attr("dy", ".35em")
.text(function(d) {
return d.data.statusid;
});
function midAngle(d){
return d.startAngle + (d.endAngle - d.startAngle)/2;
}
text.transition().duration(1000)
.attrTween("transform", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
var pos = outerArc.centroid(d2);
pos[0] = radius * (midAngle(d2) < Math.PI ? 1 : -1);
return "translate("+ pos +")";
};
})
.styleTween("text-anchor", function(d){
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
return midAngle(d2) < Math.PI ? "start":"end";
};
});
text.exit()
.remove();
/* ==============================================================
Drawning the inside-labels
============================================================== */
var arcs = svg.selectAll(".arc");
// Add a magnitude value to the larger arcs, translated to the arc centroid and rotated.
arcs.filter(function(d) { return d.endAngle - d.startAngle > .2; }).append("svg:text")
.attr("dy", ".35em")
.attr("text-anchor", "middle")
//.attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")rotate(" + angle(d) + ")"; })
.attr("transform", function(d) { //set the label's origin to the center of the arc
//we have to make sure to set these before calling arc.centroid
d.outerRadius = arc.outerRadius; // Set Outer Coordinate
d.innerRadius = arc.outerRadius/2; // Set Inner Coordinate
console.log('omg');
return "translate(" + arc.centroid(d) + ")";
})
.style("fill", "White")
.style("font", "bold 12px Arial")
.text(function(d) { return (d.data.price*100/sumprice).toFixed(1)+'%'; });
function angle(d) {
var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;
return a > 90 ? a - 180 : a;
}
/* ==============================================================
Drawning the label-lines
============================================================== */
var polyline = svg.select(".lines").selectAll("polyline")
.data(pie(data), key);
polyline.enter()
.append("polyline");
polyline.transition()
.attrTween("points", function(d){
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
var pos = outerArc.centroid(d2);
pos[0] = radius * 0.95 * (midAngle(d2) < Math.PI ? 1 : -1);
return [arc.centroid(d2), outerArc.centroid(d2), pos];
};
});
polyline.exit()
.remove();

Categories

Resources