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> | |