Skip to content

Instantly share code, notes, and snippets.

@yang-wei
Created August 7, 2016 10:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save yang-wei/6e1566e2e769b4180db3e09f72515400 to your computer and use it in GitHub Desktop.
Save yang-wei/6e1566e2e769b4180db3e09f72515400 to your computer and use it in GitHub Desktop.
react d3 (v4.0) stacked bar chart using rd3
'use strict';
import { scaleOrdinal, schemeCategory20c } from 'd3-scale';
import React from 'react';
module.exports = React.createClass({
displayName: 'BarChart',
propTypes: {
colors: React.PropTypes.func,
data: React.PropTypes.array.isRequired,
xScale: React.PropTypes.func.isRequired,
xAccessor: React.PropTypes.func,
yScale: React.PropTypes.func.isRequired,
svgComponent: React.PropTypes.any,
transform: React.PropTypes.string,
},
getDefaultProps() {
return {
colors: scaleOrdinal(schemeCategory20c),
xAccessor: d => d.x,
SvgComponent: (props) => <rect {...props} />,
transform: 'translate(0 ,0)',
};
},
_renderSeries(stackedData) {
return stackedData.map(item => {
const { key, index } = item
const data = Array.from(item)
return data.map(d => {
return this._renderItem(d, key, index)
})
});
},
_renderItem(item, key, index) {
const { colors, xScale, yScale, SvgComponent, xAccessor } = this.props;
const x = xScale(xAccessor(item['data']))
const y = yScale(item[1]);
const height = yScale(item[0]) - yScale(item[1]);
const width = xScale.rangeBand()
return (
<SvgComponent
x={x}
y={y}
height={height}
width={width}
fill={colors(index)}
item={item}
item-key={key}
item-index={index}
/>
);
},
render() {
const props = this.props;
return (
<g transform={props.transform}>
{this._renderSeries(props.data)}
</g>
);
},
});
import { Component } from 'react'
import { BarChart } from '../src/barchart'
import { stack } from 'd3-shape'
import SvgContainer from '../src/common/charts/SvgContainer';
import { XAxis, YAxis } from '../src/common';
var barData = [
{month: new Date(2015, 0, 1), apples: 3840, bananas: 1920, cherries: 960, dates: 400},
{month: new Date(2015, 1, 1), apples: 1600, bananas: 1440, cherries: 960, dates: 400},
{month: new Date(2015, 2, 1), apples: 640, bananas: 960, cherries: 640, dates: 400},
{month: new Date(2015, 3, 1), apples: 320, bananas: 480, cherries: 640, dates: 400}
];
const width = 500;
const height = 200;
// stacked
const stacked = stack()
.keys(['apples', 'bananas', 'cherries', 'dates'])
const stackedData = stacked(barData)
// xScale
const xDomain = barData.map(d => d.month)
const xScale = d3.scale.ordinal()
.domain(xDomain)
.rangeRoundBands([0, width], 0.25);
const xAccessor = d => d['month']
// yScale
// in stacked bar chart, the maximum height we need for
// yScale domain is the sum of y0 + y
const maxYDomain = d3.max(stackedData, (d) => (
d3.max(d, (d2) => (
// where y0, y is generated by d3.layout.stack()
d2[0] + d2[1]
))
));
const yDomain = [0, maxYDomain];
const yScale = d3.scale.linear().range([height, 0]).domain(yDomain);
let isMouseOver = false
class Rect extends Component {
getInitialState() {
return {
fill: this.props.fill
}
}
render() {
console.log(this.props)
console.log(this.state)
return (
<rect
{...this.props}
fill={this.state.fill}
/>
)
}
}
export default class MyBarChart extends Component {
render() {
return (
<SvgContainer width={width}>
<BarChart
data={stackedData}
width={width}
height={height}
xScale={xScale}
yScale={yScale}
xAccessor={xAccessor}
transform={'translate(50, 0)'}
SvgComponent={Rect}
/>
<XAxis
width={width}
height={height}
xScale={xScale}
tickFormatting={d => d.getMonth() + 1 }
transform={'translate(50, 200)'}
/>
<YAxis
width={width}
height={height}
yScale={yScale}
transform={'translate(50, 0)'}
/>
</SvgContainer>
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment