// Quick charting tool for helping with infographics // Configurable params // Click on the number and see a magic slider appears to tweak it. var config = { startRadius: 107, thickness: 17, colorRange: ['#30f400', '#00660f'], animate: !false }; // If the data file is foo.csv, then use tributary.foo to read that csv. // Note: please have no space around comma in the csv file. //var chartData = tributary.chart_data; //chartData = sanitize(chartData); d3.csv('chart_data.csv', function (json) { var data = sanitize(json); drawChart(data); }); var svg = d3.select('svg'); var gRoot = svg.append('svg:g') .attr('transform', 'translate(353, 240)'); var arc = d3.svg.arc(); var tau = 2 * Math.PI; var colorScale = d3.scale.linear() .domain([0, 100]) .interpolate(d3.interpolateRgb) .range(config.colorRange); var opacityScale = d3.scale.linear() .domain([0, 100]) .range([0.3, 1]); //==================================================================== function sanitize(data) { data.forEach(function (d) { if (d.value > 100) { d.value = 100; } if (d.value < 0) { d.value = 0; } }) data.sort(function (a, b) { var v1 = +a.value; var v2 = +b.value; if (v1 === v2) { return 0; } return (v1 < v2 ? -1 : 1); }); return data; } //==================================================================== function getRandomValue() { return Math.floor(Math.random() * 100); } //==================================================================== function arcTween(transition) { console.log('in arctween', transition); transition.attrTween('d', function (d) { //console.log('inside attrtween', d); var interpolate = d3.interpolate(d.endAngleStart, d.endAngle); return function (t) { d.arcFn.endAngle(interpolate(t)); return d.arcFn(d); } }); } //==================================================================== function drawChart(chartData) { var g = gRoot.selectAll('g.arc') .data(chartData) .enter() .append('g') .attr('class', 'arc'); gRoot.append('svg:text') .attr({ x: -(config.startRadius + chartData.length * config.thickness), y: config.startRadius + chartData.length * config.thickness + 50 }) .style('fill', '#777') .text('click to change'); var arcPath = g.append('svg:path') .attr('d', function (d, i) { var endAngle = d.value / 100 * tau; var arc = d3.svg.arc(); arc .innerRadius(config.startRadius + i * config.thickness) .outerRadius(config.startRadius + (i+1) * config.thickness) .startAngle(0) .endAngle(endAngle); d.arcFn = arc; if (config.animate) { arc.endAngle(0); d.endAngleStart = 0; d.endAngle = endAngle; } return arc(); }) .style('fill', function (d) { return config.colorRange[0]; }) .style('fill-opacity', function (d) { return 1; //return opacityScale(d.value); }) .style('stroke-width', 2) .style('stroke-opacity', 0.216) .style('stroke', 'white'); // show labels g.append('svg:text') .attr({ x: 2, y: function (d, i) { return -config.startRadius - i * config.thickness - 3 } }) .style('font-size', '11px') .style('fill', 'white') .text(function (d) { return d.key; }); if (config.animate) { arcPath .transition() .duration(750) .call(arcTween) .style('fill', function (d) { return colorScale(d.value); }); } else { arcPath .style('fill', function (d) { return colorScale(d.value); }); } } //==================================================================== function simulateChange() { var arcPath = d3.selectAll('g.arc path'); arcPath.attr('d', function (d) { d.value = getRandomValue(); var rndEndAngle = d.value / 100 * tau; if (config.animate) { d.endAngleStart = d.endAngle; d.endAngle = rndEndAngle; } else { d.arcFn.endAngle(rndEndAngle); } return d.arcFn(); }); if (config.animate) { arcPath .transition() .duration(750) .call(arcTween) .style('fill', function (d) { return colorScale(d.value); }); } else { arcPath .style('fill', function (d) { return colorScale(d.value); }); } } svg.on('click', function () { simulateChange(); });