This is a beautified version of Mike Bostock's Circular Segment.
Checkout the live demo.
This is a beautified version of Mike Bostock's Circular Segment.
Checkout the live demo.
| function fix(k) { | |
| var t0, t1 = k * 2 * Math.PI; | |
| // Solve for theta numerically. | |
| if (k > 0 && k < 1) { | |
| t1 = Math.pow(12 * k * Math.PI, 1 / 3); | |
| for (var i = 0; i < 10; ++i) { | |
| t0 = t1; | |
| t1 = (Math.sin(t0) - t0 * Math.cos(t0) + 2 * k * Math.PI) / (1 - Math.cos(t0)); | |
| } | |
| k = (1 - Math.cos(t1 / 2)) / 2; | |
| } | |
| return k; | |
| } | |
| function drawCircularProgressBar(selection, k) { | |
| if (selection) { | |
| var r = 240; // radius of the ball | |
| var h = 0; | |
| var zero = 0; | |
| var one = 0; | |
| var text = "N/A"; | |
| if (k >= 0) { | |
| var fixed = fix(k); | |
| h = r * 2 * (1 - fixed); | |
| zero = 1; | |
| one = k; | |
| text = parseInt(k * 100) + "%"; | |
| } | |
| selection.selectAll("svg").remove(); | |
| selection.append("svg").attr("width", "100%").attr("height", "100%") | |
| .attr("viewBox", "0 0 " + r*2 + " " + r*2) | |
| .call(function(e) { | |
| var defs = e.append("defs") | |
| var clip = defs.append("clipPath").attr("id", "clip") | |
| .append("rect").attr("x", "-" + r).attr("y", "-" + r) | |
| .attr("width", r*2).attr("height", h); | |
| g = e.append("g").attr("transform", "translate(" + r + "," + r + ")"); | |
| g.append("circle").attr("r", r).attr("class", "na"); | |
| g.append("circle").attr("r", r).style("fill-opacity", zero).attr("class", "zero"); | |
| g.append("circle").attr("r", r).style("fill-opacity", one).attr("class", "one"); | |
| g.append("circle").attr("r", r).style("fill", "#333").style("fill-opacity", 0.5).attr("clip-path", "url(#clip)"); | |
| g.append("text").attr("class", "value").attr("text-anchor", "middle").attr("font-size", "100").style("fill", "white").style("fill-opacity", .7).text(text); | |
| }); | |
| } | |
| } | |
| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <link rel="stylesheet" type="text/css" href="style.css"> | |
| <body> | |
| <div id="input"> | |
| <form oninput="output.value = (input.value / 240).toFixed(3)" style="top:10px;left:10px;"> | |
| <input id="input" type="range" min="0" max="240" value="60" style="width:240px;"> | |
| <i>k</i> = <output name="output" for="input">0.250</output> | |
| </form> | |
| </div> | |
| <div id="main"> | |
| </div> | |
| <script src="http://d3js.org/d3.v3.min.js"></script> | |
| <script src="circular-progress-bar.js"></script> | |
| <script> | |
| d3.select("#main").call(drawCircularProgressBar, .25); | |
| d3.select("form").on("input", function() { d3.select("#main").call(drawCircularProgressBar, +this.output.value); }); | |
| </script> | |
| </body> |
| #main { | |
| height: 300px; | |
| width: 300px; | |
| } | |
| circle.na { | |
| fill: #333; | |
| } | |
| circle.zero { | |
| fill: #c00; | |
| } | |
| circle.one { | |
| fill: #6c0; | |
| } |