UNPKG

d3rrc

Version:

Reusable D3 Charts for React.js

183 lines (167 loc) 5.14 kB
var React = require('react'); var Support = require('../lib/support'); var d3 = require('d3'); var PieChart = React.createClass({ chart: function(selection){ var idx = 1; var { margin, width, height, duration, identity, innerRadius, sliceText, style, value: getValue, colorRange, color, text: getText, getIdentity, enterSlice, updateSlice, exitSlice, } = Support.getProps(this, 'chart', { margin: Support.types.Object({ top: Support.types.Number(20), right: Support.types.Number(10), bottom: Support.types.Number(20), left: Support.types.Number(50) }), width: Support.types.Number(-1), height: Support.types.Number(500), duration: Support.types.Number(500), identity: Support.types.String('_id'), innerRadius: Support.types.Number(0), sliceText: Support.types.Function(function(){}), style: Support.types.Object(false), value: Support.types.Function(function x(d){ return +d.value; }), colorRange: Support.types.Function(false), color: Support.types.Function(false), text: Support.types.Function(function(d){ return d.text||''; }), getIdentity: Support.types.Function(function(d){ return d.data[identity] || (d.data[identity] = ++idx); }), enterSlice: Support.types.Function(function(node, arc){ node.append('path') .style('fill', function(d){ return color(d.data); }) .append('title') ; node.append("text") .attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; }) .attr("dy", ".35em") .style("text-anchor", "middle") .text(function(d) { return getText(d.data); }); }), updateSlice: Support.types.Function(function(node, arc){ node.select('path') .style('fill', function(d){ return color(d.data); }) .attrTween('d', function(d){ this._current = this._current || d; var interpolate = d3.interpolate(this._current, d); this._current = interpolate(0); return function(t) { return arc(interpolate(t)); }; }); node.select('title') .text(sliceText); node.select('text') .attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; }) .text(function(d) { return getText(d.data); }); }), exitSlice: Support.types.Function(function(node, arc){}) }); color = color || function(d){ return d.color||colorRange(getValue(d), d, d[identity]); }; selection.each(function(data){ var wid = width===-1?this.offsetWidth:width; var w = wid - margin.left - margin.right; var h = height - margin.top - margin.bottom; var r = (w>h)?Math.floor(h/2):Math.floor(w/2); var svg = d3.select(this).select('svg'); var min = d3.min(data, getValue), max = d3.max(data, getValue); var i=0, l=data.length; for(;i<l; i++){ data[i][identity] = data[i][identity] || idx++; } colorRange = colorRange || d3.scale.linear().domain([min, max]).range(["#ddd", "#333"]); if(!svg[0][0]){ svg = d3.select(this).append('svg'); } svg .attr('width', wid) .attr('height', height) ; var arc = d3.svg.arc() .outerRadius(r) .innerRadius(innerRadius); var pie = d3.layout.pie() .value(getValue); var main = svg.select('g'); var slices = main.select('.slices'); if(!main[0][0]){ main = svg.append('g'); slices = main.append('g').attr('class', 'slices'); } main .attr('transform', 'translate('+(margin.left+(w/2))+', '+(margin.top+(h/2))+')') ; var slice = slices.selectAll('g.slice') .data(pie(data, getIdentity)); ; var sliceEnter = slice.enter() .append('g') .attr('class', 'slice') ; enterSlice(sliceEnter, arc); updateSlice(slice.transition().duration(duration), arc); var sliceExit = slice.exit() .remove() ; exitSlice(sliceExit); if(style){ Object.keys(style).forEach(function(key){ svg.selectAll(key).attr('style', style[key]); }); } }); }, renderChart: function(data){ if(!data){ return; } var container = this.getDOMNode(); d3.select(container) .datum(data) .call(this.chart) ; }, componentDidMount: function(){ return this.renderChart(this.props.data); }, componentDidUpdate: function(){ return this.renderChart(this.props.data); }, render: function(){ var classNames = Support.classList(this, { 'bar-chart': true }); return ( <div className={classNames}> </div> ); } }); module.exports = { PieChart: PieChart };