UNPKG

d3rrc

Version:

Reusable D3 Charts for React.js

138 lines (123 loc) 3.82 kB
var React = require('react'); var Support = require('../lib/support'); var d3 = require('d3'); var TimeSeriesChart = React.createClass({ chart: function(selection){ var _scale = d3.time.scale(); var lscale = d3.scale.linear(); var _X = function(d){ return xScale(xValue(d)); }; var _Y = function(d){ return yScale(yValue(d)); }; var { margin, width, height, xValue, yValue, xScale, yScale, xAxis, area, line, style } = Support.getProps(this, 'chart', { margin: Support.types.Object({ top: Support.types.Number(20), right: Support.types.Number(20), bottom: Support.types.Number(20), left: Support.types.Number(20) }), width: Support.types.Number(-1), height: Support.types.Number(120), style: Support.types.Object(false), xValue: Support.types.Function(function(d) { return d[0]; }), yValue: Support.types.Function(function(d) { return d[1]; }), xScale: Support.types.Function(_scale), yScale: Support.types.Function(lscale), xAxis: Support.types.Function(d3.svg.axis().scale(_scale).orient("bottom").tickSize(6, 0)) }); var area = d3.svg.area().x(_X).y1(_Y); var line = d3.svg.line().x(_X).y(_Y); selection.each(function(data) { var w = width===-1?this.offsetWidth:width; // Convert data to standard representation greedily; // this is needed for nondeterministic accessors. data = data.map(function(d, i) { return [xValue.call(data, d, i), yValue.call(data, d, i)]; }).sort(function(a, b){ return a[0]-b[0]; }); // Update the x-scale. xScale .domain(d3.extent(data, function(d) { return d[0]; })) .range([0, w - margin.left - margin.right]); // Update the y-scale. yScale .domain([0, d3.max(data, function(d) { return d[1]; })]) .range([height - margin.top - margin.bottom, 0]); // Select the svg element, if it exists. var svg = d3.select(this).selectAll("svg").data([data]); // Otherwise, create the skeletal chart. var gEnter = svg.enter().append("svg").append("g"); gEnter.append("path").attr("class", "area"); gEnter.append("path").attr("class", "line"); gEnter.append("g").attr("class", "x axis"); // Update the outer dimensions. svg .attr("width", w) .attr("height", height); // Update the inner dimensions. var g = svg.select("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // Update the area path. g.select(".area") .attr("d", area.y0(yScale.range()[0])); // Update the line path. g.select(".line") .attr("d", line); // Update the x-axis. g.select(".x.axis") .attr("transform", "translate(0," + yScale.range()[0] + ")") .call(xAxis); 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 = { TimeSeriesChart: TimeSeriesChart };