👉 exercise1/js/Chart/index.js
defaultData = [60, 40, 20]
defaultProps = {
stroke: '#ccc',
strokeWidth: '2px',
fill: 'steelblue',
}
selection(selector) {
if (!selector) return this._selection;
this._selection = d3.select(selector);
return this;
}
data(arr) {
if (!arr) return this._data || this.defaultData;
this._data = arr;
return this;
}
props(obj) {
if (!obj) return this._props || this.defaultProps;
this._props = merge(this._props || this.defaultProps, obj);
return this;
}
draw() {
const data = this.data();
const props = this.props();
console.log('My chart DATA', data);
console.log('My chart PROPS', props);
}
👉 exercise1/js/Container/index.js
Import chart:
import Chart from '../Chart';
Attach new instance to component:
chart = new Chart()
Change the render method:
render() {
return (
<div id='chart' />
);
}
Call chart in lifecycle method:
componentDidMount() {
this.chart
.selection('#chart')
.draw();
}
👀 Check your console!
Add some additional calls:
setTimeout(() => {
this.chart
.data([20, 34, 48, 60])
.props({ fill: '#F86F00' })
.draw();
}, 1000);
setTimeout(() => {
this.chart
.data([30, 50, 30])
.props({ fill: '#007BC7' })
.draw();
}, 2000);
👉 exercise1/js/Chart/index.js
Swap out your draw function for a real chart:
draw() {
const data = this.data();
const props = this.props();
const node = this.selection().node();
const { width, height } = node.getBoundingClientRect();
const t = d3.transition()
.duration(750);
const g = this.selection()
.appendSelect('svg')
.attr('width', width)
.attr('height', height)
.appendSelect('g')
.attr('transform', 'translate(' + (width / 2 - 62) + ', 60)');
const circles = g.selectAll('circle')
.data(data, (d, i) => i);
circles
.style('fill', props.fill)
.style('stroke', props.stroke);
circles.enter().append('circle')
.style('fill', props.fill)
.style('stroke', props.stroke)
.style('stroke-width', props.strokeWidth)
.attr('cy', '0')
.attr('cx', (d, i) =>
data.slice(0, i).reduce((a, b) => a + b, 0) + (d / 2)
)
.merge(circles)
.transition(t)
.attr('cx', (d, i) =>
data.slice(0, i).reduce((a, b) => a + b, 0) + (d / 2)
)
.attr('r', d => d / 2);
circles.exit()
.transition(t)
.attr('r', 0)
.remove();
}