Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
React + D3 (v2)

Multi-series bar chart rendered using React and D3.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>React + d3</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/react/0.8.0/react.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/react/0.8.0/JSXTransformer.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/d3/3.3.13/d3.js"></script>
</head>
<body>
<div id="container"> </div>
<script type="text/jsx">
/** @jsx React.DOM */
var Chart = React.createClass({
render: function() {
return (
<svg width={this.props.width} height={this.props.height}>{this.props.children}</svg>
);
}
});
var Bar = React.createClass({
getDefaultProps: function() {
return {
width: 0,
height: 0,
x: 0,
y: 0
}
},
render: function() {
return (
<rect fill={this.props.color}
width={this.props.width} height={this.props.height}
x={this.props.x} y={this.props.y} />
);
}
});
var DataSeries = React.createClass({
getDefaultProps: function() {
return {
title: '',
data: []
}
},
render: function() {
var self = this,
props = this.props,
refs = props.__owner__.refs
size = props.size,
width = size.width,
height = size.height;
var yScale = props.yScale;
var xScale = d3.scale.ordinal()
.domain(d3.range(props.data.length))
.rangeRoundBands([0, width], 0.05);
var otherSeries = _.chain(refs)
.values()
.reject(function(component) { return component === self; })
.value();
var bars = _.map(props.data, function(point, i) {
var yOffset = _.reduce(otherSeries, function(memo, series) {
return memo + series.props.data[i];
}, 0);
return (
<Bar height={yScale(point)} width={xScale.rangeBand()} x={xScale(i)} y={size.height - yScale(yOffset) - yScale(point)} color={props.color} key={i} />
)
});
return (
<g>{bars}</g>
);
}
});
var StackedBarChart = React.createClass({
getDefaultProps: function() {
return {
width: 600,
height: 300
}
},
render: function() {
var data = this.props.data,
size = { width: this.props.width, height: this.props.height };
var zipped = _.zip(data.series1, data.series2, data.series3);
var totals = _.map(zipped, function(values) {
return _.reduce(values, function(memo, value) { return memo + value; }, 0);
});
var yScale = d3.scale.linear()
.domain([0, d3.max(totals)])
.range([0, this.props.height]);
return (
<Chart width={this.props.width} height={this.props.height}>
<DataSeries data={data.series1} size={size} yScale={yScale} ref="series1" color="cornflowerblue" />
<DataSeries data={data.series2} size={size} yScale={yScale} ref="series2" color="red" />
<DataSeries data={data.series3} size={size} yScale={yScale} ref="series3" color="green" />
</Chart>
);
}
});
var data = {
series1: [ 30, 10, 5, 8, 15, 10 ],
series2: [ 5, 20, 12, 4, 6, 2 ],
series3: [ 5, 8, 2, 4, 6, 2 ]
};
React.renderComponent(
<StackedBarChart data={data} />,
document.getElementById('container')
);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment