// Define the margin, radius, and color scale. Colors are assigned lazily, so // if you want deterministic behavior, define a domain for the color scale. var m = 10 , r = 100 , z = d3.scale.category20c() , csv, pie, arc, pages, svg, g; // handy for page inspection in dev tools d3.csv('histogram.csv', function(hist) { csv = hist; // Define a pie layout: the pie angle encodes the count of flights. Since our // data is stored in CSV, the counts are strings which we coerce to numbers. pie = d3.layout.pie() .value(function(d) { return +d.count; }) .sort(function(a, b) { return a.time - b.time; }); // Define an arc generator. Note the radius is specified here, not the layout. arc = d3.svg.arc() .innerRadius(r / 2) .outerRadius(r); // Nest the page load time data by page. Our data has page load time in // 2-second resolution, upper bound, but we want to group counts by page. pages = d3.nest() .key(function(d) { return d.page; }) .entries(hist); // Insert an svg element (with margin) for each page in our dataset. A // child g element translates the origin to the pie center. svg = d3.select('body').selectAll('div') .data(pages) // http://code.google.com/p/chromium/issues/detail?id=98951 .enter().append('div') .style('display', 'inline-block') .style('width', (r + m) * 2 + 'px') .style('height', (r + m) * 2 + 'px') .append('svg:svg') .attr('width', (r + m) * 2) .attr('height', (r + m) * 2) .append('svg:g') .attr('transform', 'translate(' + (r + m) + ',' + (r + m) + ')'); // Add a label for the page. The `key` comes from the nest operator. svg.append('svg:text') .attr('dy', '.35em') .attr('text-anchor', 'middle') .text(function(d) { return d.key; }); // Pass the nested per-page values to the pie layout. The layout computes // the angles for each arc. Another g element will hold the arc and its label. g = svg.selectAll('g') .data(function(d) { return pie(d.values); }) .enter().append('svg:g'); // Add a colored arc path, with a mouseover title showing the count. g.append('svg:path') .attr('d', arc) .style('fill', function(d) { return z(d.data.time); }) .append('svg:title') .text(function(d) { return '<' + d.data.time + ': ' + d.data.count; }); // Add a label to the larger arcs, translated to the arc centroid and rotated. g.filter(function(d) { return d.endAngle - d.startAngle > .2; }).append('svg:text') .attr('dy', '.35em') .attr('text-anchor', 'middle') .attr('transform', function(d) { return 'translate(' + arc.centroid(d) + ')rotate(' + angle(d) + ')'; }) .text(function(d) { return '<' + d.data.time; }); d3.select(self.frameElement).style('height', (document.body.offsetHeight) +'px'); }); // Computes the label angle of an arc, converting from radians to degrees. function angle(d) { var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90; return a > 90 ? a - 180 : a; }