The basics of drawing data-driven arcs by using values to determine the arc length. Very stripped down to give beginners an idea of how to draw and color shapes using the accessor functions in D3. For transitions and tweens, check out Bostock's well-annotated example, or my second arc example.
Idea was used for my SF Muni webapp (gist).
al lin, aug. 2013
xxxxxxxxxx
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="description" content="Basic beginner's source code to drawing arcs in D3 using dynamically-generated data.">
<title>JavaScript D3: Drawing Concentric Arcs (Part I)</title>
<style type='text/css'>
.click-circle{
cursor: pointer;
}
</style>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.2.2/d3.v3.min.js"></script>
</head>
<body>
<div class="chart"></div>
<script type="text/javascript">
var width = window.innerWidth,
height = window.innerHeight;
// append svg to the DIV
d3.select(".chart").append("svg:svg")
.attr("width", width)
.attr("height", height);
var render = function(dataset) {
vis = d3.select("svg"); // select the svg
// set constants
var PI = Math.PI;
var arcMin = 75; // inner radius of the first arc
var arcWidth = 15; // width
var arcPad = 1; // padding between arcs
// arc accessor
// d and i are automatically passed to accessor functions,
// with d being the data and i the index of the data
var drawArc = d3.svg.arc()
.innerRadius(function(d, i) {
return arcMin + i*(arcWidth) + arcPad;
})
.outerRadius(function(d, i) {
return arcMin + (i+1)*(arcWidth);
})
.startAngle(0 * (PI/180))
.endAngle(function(d, i) {
return d*6 * (PI/180);
});
// bind the data
var arcs = vis.selectAll("path.arc-path").data(dataset);
// *** update existing arcs -- redraw them ***
arcs.attr("d", drawArc)
.attr("fill", function(d){
// we need to redefine the fills as well since we have new data,
// otherwise the colors would no longer be relative to the data
// values (and arc length). if your fills weren't relative to
// the data, this would not be necessary
var grn = Math.floor((1 - d/60)*255);
return "rgb(0, "+ grn +", 0)";
});
// draw arcs for new data
arcs.enter().append("svg:path")
.attr("class", "arc-path") // assigns a class for easier selecting
.attr("transform", "translate(400,200)") // sets position--easier than setting x's and y's
.attr("fill", function(d){
// fill is an rgb value with the green value determined by the data
// smaller numbers result in a higher green value (1 - d/60)
// you should also look into using d3 scales to create gradients
var grn = Math.floor((1 - d/60)*255);
return "rgb(0, "+ grn +", 0)";
})
.attr("d", drawArc); // draw the arc
};
// you can safely ignore the code below.
// the code is used to create a click area for people to regenerate
// arcs by generating a new data set and calling render on that set
// for generating a random array of times
var generateTimes = function(quantity) {
var i, times = [];
for(i=0; i<quantity; i++) {
times.push(Math.round(Math.random()*60));
}
return times;
};
// drawing the click area
var initialize = function() {
var arcMin = 75; // this should match the arcMin in render()
var times = generateTimes(6);
render(times);
// making the click circle
if(!d3.selectAll("circle.click-circle")[0].length) { // if there is no click area..
d3.select("svg").append("circle")
.attr("class", 'click-circle')
.attr("transform", "translate(400,200)")
.attr("r", arcMin*0.85)
.attr("fill", "rgba(201, 201, 201, 0.5)")
.on("click", function(d) {
times = generateTimes(6);
render(times);
});
}
}
initialize();
</script>
</body>
</html>
Modified http://cdnjs.cloudflare.com/ajax/libs/d3/3.2.2/d3.v3.min.js to a secure url
https://cdnjs.cloudflare.com/ajax/libs/d3/3.2.2/d3.v3.min.js