a factory that creates a vertically stacked series of rings reflecting percents.
forked from rcrocker13's block: Arc Tween
forked from headwinds's block: Arc Tween Percent Rings
license: gpl-3.0 |
a factory that creates a vertically stacked series of rings reflecting percents.
forked from rcrocker13's block: Arc Tween
forked from headwinds's block: Arc Tween Percent Rings
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<body> | |
<style> | |
text { | |
font-family: Georgia, Arial, sans-serif; | |
font-size: 25px; | |
fill: black; | |
} | |
.gold { | |
fill: gold; | |
} | |
.blue { | |
fill: blue; | |
} | |
.red { | |
fill: red; | |
} | |
</style> | |
<script src="https://d3js.org/d3.v5.min.js"> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script> | |
<script> | |
var width = 500, | |
height = 300, | |
τ = 2 * Math.PI; // http://tauday.com/tau-manifesto | |
// An arc function with all values bound except the endAngle. So, to compute an | |
// SVG path string for a given angle, we pass an object with an endAngle | |
// property to the `arc` function, and it will return the corresponding string. | |
var arc = d3.arc() | |
.innerRadius(40) | |
.outerRadius(45) | |
.startAngle(0); | |
// Create the SVG container, and apply a transform such that the origin is the | |
// center of the canvas. This way, we don't need to position arcs individually. | |
var svg = d3.select("body").append("svg") | |
.attr("width", width) | |
.attr("height", height); | |
var rings = [{id:"gold", percent: 80}, | |
{id:"red", percent: 40}, | |
{id:"blue", percent: 10}]; | |
var d3Rings = []; | |
var convertPercentToAngle = (percent) => { return ( percent / 100 ) * τ }; | |
var createRings = function(){ | |
rings.map(function(ring,index){ | |
var d3Ring = svg | |
.append("g") | |
.attr("transform", "translate(" + width / 2 + "," + ( ( 100 * index ) + 50 ) + ")") | |
.attr("id",ring.id); | |
// background | |
d3Ring | |
.append("path") | |
.datum({endAngle: τ}) | |
.style("fill", "#ddd") | |
.attr("d", arc); | |
// foreground | |
var foreground = d3Ring | |
.append("path") | |
.datum({endAngle: 0}) | |
.style("fill", ring.id) | |
.style("stroke", "none") | |
.style("stroke-width", "0px") | |
.style("opacity", 1) | |
.attr("d", arc); | |
// text | |
d3Ring | |
.append("text") | |
.attr("x", -22) | |
.attr("y", 8) | |
.text(ring.percent + "%") | |
.attr("class", ring.id); | |
var angle = convertPercentToAngle(ring.percent); | |
foreground | |
.transition() | |
.duration(1500) | |
.delay(500 * index) | |
.call(arcTween, angle); | |
d3Rings.push(d3Ring); | |
}); | |
} | |
createRings(); | |
function arcTween(transition, newAngle) { | |
transition.attrTween("d", function(d) { | |
var interpolate = d3.interpolate(d.endAngle, newAngle); | |
return function(t) { | |
d.endAngle = interpolate(t); | |
return arc(d); | |
}; | |
}); | |
} | |
</script> | |