Created
January 29, 2015 18:18
-
-
Save albertsun/90339d1b64cd9b4ae203 to your computer and use it in GitHub Desktop.
Drawing partial circles with area proportional to a value (good!) or angle proportional to a value (misleading!)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function() { | |
var circleSegment = {}; | |
var degreesToRadians = function(deg) { | |
return deg*Math.PI*2/360; | |
}; | |
// takes an angle in radians | |
// returns 0-1 the proportion of a circle's area | |
// that a segment bounded by arc of that angle fills | |
// (allowing segment to range in size to the full circle) | |
var angleToProportion = function(radians) { | |
return (radians-Math.sin(radians))/(2*Math.PI); | |
}; | |
var calc_table = []; | |
for (var i=1;i<=360;i++) { | |
calc_table.push(angleToProportion(degreesToRadians(i))); | |
} | |
// takes a 0-1 proportion of area | |
// returns the angle of arc in radians that defines a circle segment | |
// filling that proportion of the circle | |
// accurate to within 1/360th of a circle (1°) | |
var proportionToAngle = function(proportion) { | |
proportion = proportion % (2*Math.PI); | |
var curr = calc_table[0]; | |
for (var i=0;i<360;i++) { | |
if (calc_table[i] > proportion) { | |
return degreesToRadians(Math.abs( calc_table[i-1]-proportion ) < Math.abs( calc_table[i]-proportion ) ? i : i+1); | |
} | |
} | |
return degreesToRadians(calc_table.length); | |
}; | |
circleSegment.angleToProportion = angleToProportion; | |
circleSegment.proportionToAngle = proportionToAngle; | |
if (typeof define === 'function' && define.amd) { | |
define([], function() { | |
return circleSegment; | |
}); | |
} else { | |
this.circleSegment = circleSegment; | |
} | |
}).call(this); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
body { | |
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | |
position: relative; | |
} | |
svg { | |
display: inline-block; | |
margin: 3px; | |
} | |
svg circle, | |
svg path { | |
stroke-width: 0; | |
opacity: 1; | |
} | |
svg .proportional { | |
fill: #2ca02c; | |
} | |
svg .naive { | |
fill: #d62728; | |
} | |
</style> | |
<body> | |
<div> | |
<svg width="360" height="40"> | |
<circle r="20" cx="20" cy="20" class="proportional" /><text y="20" x="45">Area Proportional</text> | |
<circle r="20" cx="200" cy="20" class="naive" /><text y="20" x="225">Angle Proportional</text> | |
</svg> | |
</div> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script src="circle-segment.js"></script> | |
<script> | |
function partialCircle(radius, radians) { | |
// var radians = circleSegment.proportionToAngle(proportion); | |
var rotation = (((1*Math.PI)-radians)/2)+radians; | |
var dimension = 2 * radius, | |
points = 50; | |
var angle = d3.scale.linear() | |
.domain([0, points-1]) | |
.range([0-rotation, radians-rotation]); | |
var line = d3.svg.line.radial() | |
.interpolate("basis") | |
.tension(0) | |
.radius(radius) | |
.angle(function(d, i) { return angle(i); }); | |
return line(d3.range(points)); | |
} | |
var pct = d3.format("%"); | |
// var radians = circleSegment.proportionToAngle(proportion); | |
d3.range(1,101).forEach(function(i) { | |
var radius = 20; | |
var height = radius*2, | |
width = (radius*4)+100; | |
var svg = d3.select("body").append("svg"); | |
svg.attr("width", width) | |
.attr("height", height); | |
var radians = circleSegment.proportionToAngle(i/100); // proportional to area | |
var radiansNaive = 2*Math.PI*i/100; // proportional to angle | |
svg.append("path") | |
.classed("proportional", true) | |
.attr("d", partialCircle(radius, radians)) | |
.attr("transform", function(d) { return "translate("+radius+","+radius+")"; }); | |
svg.append("path") | |
.classed("naive", true) | |
.attr("d", partialCircle(radius, radiansNaive)) | |
.attr("transform", function(d) { return "translate("+(3*radius)+","+radius+")"; }); | |
svg.append("text").attr("y",radius).attr("x",radius*4).text(pct(i/100)); | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment