Add external data in D3 Pie by dbuezas’s - javascript

I'm new to D3 and i'm trying to use a d3 chart for some visualizations, but i can't seem to figure out how to add data to this specific graphic:
http://bl.ocks.org/dbuezas/9306799
I tried to use:
d3.csv("data.csv", type, function(error, data) {
if (error) throw error; });
but i can't seem to find how to use it with the current setup.
I would appreciate if someone could point me in the right direction.
code:
<script>
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(["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");
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 [arc.centroid(d2), outerArc.centroid(d2), pos];
};
});
polyline.exit()
.remove();
};
</script>

Working code here.
First you need to make a json file with some data example below:
[{
"label": "Lorem ipsum",
"value": 0.719082972034812
}, {
"label": "dolor sit",
"value": 0.03566315700300038
}, {
"label": "amet",
"value": 0.14385902439244092
}, {
"label": "consectetur",
"value": 0.5280405324883759
}, {
"label": "adipisicing",
"value": 0.42760335514321923
}, {
"label": "elit",
"value": 0.7200075597502291
}, {
"label": "sed",
"value": 0.7396465912461281
}, {
"label": "do",
"value": 0.8943409691564739
}, {
"label": "eiusmod",
"value": 0.02541762450709939
}, {
"label": "tempor",
"value": 0.31414360040798783
}, {
"label": "incididunt",
"value": 0.8193990120198578
}]
Refer my plunk data.json
Then in the script load the json like this
d3.json("data.json", function(json) {
change(json);//pass the loaded the json to change function for drawing.
});

I also had the same problem, but in my case, I am coming from a ruby application. Data is loaded off the database and I can't really have a json file to be loaded in JavaScript.
I slightly modified #dbuezas examples only to have a reusable function. I am setting up the svg object and calling change inside.
I'm in a ERB views, and I have my data in ruby instance variables.
<script>
var colors = d3.scale.ordinal()
.domain(<%= #pie_categories.inspect.html_safe %>)
.range(<%= #pie_colors.inspect.html_safe %>);
var chart_data = <%= #pie_chart_data.to_json.html_safe %>;
var width = 450, height = 350;
create_pie_chart_at('#categories_pie_chart',
colors, chart_data, width, height);
</script>

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>

d3.js animation of a dougnut pie chart

I am working on an application that will be a hybrid pie chart and bubble chart -
here is a working animation for a simple doughnut pie chart.
http://jsfiddle.net/Qh9X5/8817/
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 = 560,
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.85)
.innerRadius(radius * 0.83);
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(["Lorem ipsum", "dolor sit", "amet", "consectetur", "adipisicing"])
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56"]);
function randomData (){
var labels = color.domain();
return labels.map(function(label){
return { label: label, value: Math.random() }
});
}
console.log("randomData()", randomData());
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();
};
http://jsfiddle.net/NYEaX/1487/
This is a static doughnut chart -- where I have calculated the mid-arcs -- but have lost the animation. So with the above sample of code -- where is it possible to obtain the arc.centroid(d)?
var width = 960,
height = 500,
radius = Math.min(width, height) / 2;
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var arc = d3.svg.arc()
.outerRadius(radius - 60)
.innerRadius(radius - 70);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d.value; });
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var data = [
{
"group": "<5",
"value": 1000,
"children": [
{
"group": "<5",
"label": "Mel",
"value": 1000,
"totalGroupValue": 1000
}
]
},
{
"group": "5-13",
"value": 1000,
"children": [
{
"group": "5-13",
"label": "Erica",
"value": 1000,
"totalGroupValue": 1000
}
]
},
{
"group": "14-17",
"value": 2000,
"children": [
{
"group": "14-17",
"label": "Jessica",
"value": 1500,
"totalGroupValue": 2000
},
{
"group": "14-17",
"label": "Jill",
"value": 500,
"totalGroupValue": 2000
}
]
},
{
"group": "18-24",
"value": 1300,
"children": [
{
"group": "18-24",
"label": "Jerry",
"value": 500,
"totalGroupValue": 1300
},
{
"group": "18-24",
"label": "Ben",
"value": 500,
"totalGroupValue": 1300
},
{
"group": "18-24",
"label": "Billy",
"value": 300,
"totalGroupValue": 1300
}
]
},
{
"group": "25-44",
"value": 1000,
"children": [
{
"group": "25-44",
"label": "Kelly",
"value": 1000,
"totalGroupValue": 1000
}
]
}
];
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.group);
});
arc
.outerRadius(radius - 10)
.innerRadius(0);
//create zone regions
var zones = [];
g.append("circle")
.attr("transform", function(d) {
zones[d.data.group] = arc.centroid(d);
return "translate(" + arc.centroid(d) + ")";
})
.attr("r", "1px")
.style("fill", function(d) {
return "black"//color(d.data.group);
});
g.append("g")
.attr("class", function(d,i) {
console.log("d", d)
return "bubble"+i;//color(d.data.group);
})
.attr("transform", function(d) {
zones[d.data.group] = arc.centroid(d);
return "translate(" + arc.centroid(d) + ")";
})
.attr("r", "1px")
.style("fill", function(d) {
return "black"//color(d.data.group);
});
//create zone regions
//custom bubble chart
function makeBubbles(transform, group, radius){
g.append("circle")
.attr("transform", function(d) {
return "translate("+transform+")";
})
.attr("r", radius)
.style("stroke", function(d) {
return "black";//color(group);
})
.style("fill", function(d) {
return color(group);
});
}
function bubbledata(data){
console.log("data", data)
//loop through data -- and MERGE children
var childs = [];
$.each(data, function( index, value ) {
childs.push(value.children);
});
var merged = data;//[].concat.apply([], childs);//flatterns multidimensional array
return $.extend(true, {}, {"children": merged});// return deep clone
}
function setBubbleChart(width, index, data){
//_create bubble
var diameter = width/2;//take half/width
var bubs = svg.select(".bubble"+index).append("g")
.attr("class", "bubs");
bubs.attr("transform", "translate("+-diameter/2+","+-diameter/2+")");
var bubble = d3.layout.pack()
.size([diameter, diameter])
.value(function(d) {
return d.value;
})
.padding(3);
//_create bubble
var data = bubbledata(data);
var nodes = bubble.nodes(data)
.filter(function(d) {
return !d.children;
}); // filter out the outer bubble
var bubbles = bubs.selectAll('circle')
.data(nodes);
bubbles.enter()
.insert("circle")
.attr('transform', function (d) {
return 'translate(' + d.x + ',' + d.y + ')';
})
.attr('r', function (d) {
return d.r;
})
.style("fill", function (d) {
return color(d.group);
});
bubbles = bubbles.transition()
.transition()
.duration(250)
.attr('transform', function(d) {
return 'translate(' + d.x + ',' + d.y + ')';
})
.attr('r', function (d) {
return d.r;
})
.ease('sine');
}
//loop through data and for EACH children array paint dots.
$.each(data, function( index, value ) {
setBubbleChart(100, index, value.children);
});
//custom bubble chart
function type(d) {
d.value = +d.value;
return d;
}
I've plotted the mid-arcs - but they are not being updated on a change of data?
http://jsfiddle.net/Qh9X5/10066/
function change(data) {
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();
var placeholders = svg.select(".placeholders").selectAll("circle.placeholder")
.data(pie(data), key);
placeholders.enter()
.insert("circle")
.style("fill", function(d) {
return "white";
//return color(d.data.label);
})
.attr("transform", function(d) {
return "translate(" + arc.centroid(d) + ")";
})
.attr("r", "5")
.attr("class", "placeholder");
placeholders
.transition().duration(1000)
placeholders.exit()
.remove();
};
I've managed to create an arc2 -- and animate the placeholders.
http://jsfiddle.net/Qh9X5/10068/
var svg = d3.select("#pies")
.append("svg")
.append("g")
svg.append("g")
.attr("class", "slices");
svg.append("g")
.attr("class", "placeholders");
svg.append("g")
.attr("class", "labels");
svg.append("g")
.attr("class", "lines");
var width = 560,
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.85)
.innerRadius(radius * 0.83);
var arc2 = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(0);
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(["Lorem ipsum", "dolor sit", "amet", "consectetur", "adipisicing"])
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56"]);
function randomData() {
var labels = color.domain();
return labels.map(function(label) {
return {
label: label,
value: Math.random()
}
});
}
console.log("randomData()", randomData());
change(randomData());
d3.select(".randomize")
.on("click", function() {
change(randomData());
});
function change(data) {
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();
var placeholders = svg.select(".placeholders").selectAll("circle.placeholder")
.data(pie(data), key);
placeholders.enter()
.insert("circle")
.style("fill", function(d) {
return "white";
})
.attr("r", "5")
.attr("class", "placeholder");
placeholders
.transition().duration(1000)
.attr("transform", function(d) {
console.log("arc.centroid(d)", arc2.centroid(d))
return "translate(" + arc2.centroid(d) + ")";
})
placeholders.exit()
.remove();
};
http://jsfiddle.net/Qh9X5/10075/
I have managed to merge the pie chart with the bubble chart -- if the data sets change - the animations should be stable.
var svg = d3.select("#pies")
.append("svg")
.append("g")
svg.append("g")
.attr("class", "slices");
svg.append("g")
.attr("class", "placeholders");
var width = 560,
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.85)
.innerRadius(radius * 0.83);
var arc2 = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(0);
var outerArc = d3.svg.arc()
.innerRadius(radius * 0.9)
.outerRadius(radius * 0.9);
svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
function colores_google(n) {
var colores_g = ["#f7b363", "#448875", "#c12f39", "#2b2d39", "#f8dd2f"];
return colores_g[n % colores_g.length];
}
var data = [{
"group": "<5",
"value": 1000,
"children": [{
"group": "<5",
"label": "Mel",
"value": 1000,
"totalGroupValue": 1000
}]
}, {
"group": "5-13",
"value": 1000,
"children": [{
"group": "5-13",
"label": "Erica",
"value": 1000,
"totalGroupValue": 1000
}]
}, {
"group": "14-17",
"value": 2000,
"children": [{
"group": "14-17",
"label": "Jessica",
"value": 1500,
"totalGroupValue": 2000
}, {
"group": "14-17",
"label": "Jill",
"value": 500,
"totalGroupValue": 2000
}]
}, {
"group": "18-24",
"value": 1300,
"children": [{
"group": "18-24",
"label": "Jerry",
"value": 500,
"totalGroupValue": 1300
}, {
"group": "18-24",
"label": "Ben",
"value": 500,
"totalGroupValue": 1300
}, {
"group": "18-24",
"label": "Billy",
"value": 300,
"totalGroupValue": 1300
}]
}, {
"group": "25-44",
"value": 1000,
"children": [{
"group": "25-44",
"label": "Kelly",
"value": 1000,
"totalGroupValue": 1000
}]
}];
$.each(data, function(index, value) {
value["groupid"] = index;
$.each(value.children, function(i, v) {
v["groupid"] = index;
});
});
//slices
var slice = svg.select(".slices").selectAll("path.slice")
.data(pie(data));
slice.enter()
.insert("path")
.style("fill", function(d) {
return colores_google(d.data.groupid);
})
.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();
//slices
//placeholder bubbles
var placeholders = svg.select(".placeholders").selectAll("g.placeholder")
.data(pie(data));
placeholders.enter()
.insert("g")
.attr("class", function(d, i) {
return "placeholder place" + i;
});
placeholders
.transition().duration(1000)
.attr("transform", function(d) {
return "translate(" + arc2.centroid(d) + ")";
})
placeholders.exit()
.remove();
//placeholder bubbles
//bubbles
function bubbledata(data) {
//loop through data -- and MERGE children
var childs = [];
$.each(data, function(index, value) {
childs.push(value.children);
});
return $.extend(true, {}, {
"children": data
}); // return deep clone
}
function setBubbleChart(width, index, data) {
//_create bubble
var diameter = width / 2; //take half/width
var bubs = svg.select(".place" + index).append("g")
.attr("class", "bubs");
bubs.attr("transform", "translate(" + -diameter / 2 + "," + -diameter / 2 + ")");
var bubble = d3.layout.pack()
.size([diameter, diameter])
.value(function(d) {
return d.value;
})
.padding(3);
//_create bubble
var data = bubbledata(data);
var nodes = bubble.nodes(data)
.filter(function(d) {
return !d.children;
}); // filter out the outer bubble
var bubbles = bubs.selectAll('circle')
.data(nodes);
bubbles.enter()
.insert("circle")
.attr('transform', function(d) {
return 'translate(' + d.x + ',' + d.y + ')';
})
.attr('r', function(d) {
return d.r;
})
.style("fill", function(d) {
return colores_google(d.groupid);
});
bubbles = bubbles.transition()
.transition()
.duration(250)
.attr('transform', function(d) {
return 'translate(' + d.x + ',' + d.y + ')';
})
.attr('r', function(d) {
return d.r;
})
.ease('sine');
}
//loop through data and for EACH children array paint dots.
$.each(data, function(index, value) {
setBubbleChart(100, index, value.children);
});
//custom bubble chart

D3 Donut Chart Enter with Transition

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>

create values instead of random data in d3.js

im new to d3. I found the script below (from http://bl.ocks.org/dbuezas) that will generate a random values on the chart when you press the button, my problem is instead of random, i want to put my own values on the chart. Please help.
<!DOCTYPE html>
<meta charset="utf-8">
<style>
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;
}
</style>
<body>
<button class="randomize">randomize</button>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
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(["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");
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 [arc.centroid(d2), outerArc.centroid(d2), pos];
};
});
polyline.exit()
.remove();
};
</script>
</body>
I tried doing this code below, but it doenst work.
function randomData (){
var labels = color.domain();
return labels.map(function(label){
return { label: "testlabel1",value: "41"
},
{ label: "testlabel2", value: "27"
},
{ label: "testlabel3", value: "101"
},
{ label: "testlabel4", value: "79"
}
});
}
You can try this code, it works, but it hasnt the array of data, so it runs only one time and becomes static.
function randomData (){
return [{ label: 'one', value: 10 },
{ label: 'two', value: 20 },
{ label: 'three', value: 30 },
{ label: 'four', value: 35 },
{ label: 'five', value: 5 }
];}
Here randomData () gives back the array like [object Object], I am doing the similar donut, will send you the final variant later.
You can paste JSON ARRAY in function label or make ajax call for remote data
function randomData (){
var labels = color.domain();
return labels.map(function(label){
return { /* YOUR JSON ARRAY */ }
});
}

Categories

Resources