Hey, thanks for the interest in this post, but just letting you know
that it is over 3 years old, so the content in here may not be accurate.
Source
(function () {
'use strict';
const animateLine = (WrappedComponent) => {
class Wrapper extends React.Component {
constructor(props) {
super(props);
const { xSelector, ySelector, data } = props;
let mappedData = data.map((d) => [xSelector(d), ySelector(d)]).reduce((arr, curr) => arr.concat(curr), []);
let max = data.map((d) => ySelector(d)).sort((a, b) => a - b).reverse()[0];
let liveData = mappedData.map((x, i) => i % 2 ? max : x);
this.mappedData = mappedData;
this.max = max;
this.state = {
data: liveData,
count: 0
};
}
componentWillMount() {
const animator = () => {
if (this.state.count >= this.max) {
cancelAnimationFrame(this.rafId);
return;
}
const newData = this.state.data.map((data, index) => {
if (index % 2) {
if (data > this.mappedData[index]) {
return data - 1;
}
}
return data;
});
this.setState({ data: newData, count: this.state.count + 1 });
this.rafId = requestAnimationFrame(animator);
}
this.rafId = requestAnimationFrame(animator);
}
componentWillUnmount() {
cancelAnimationFrame(this.rafId);
}
render() {
return <WrappedComponent data={this.state.data} />;
}
}
Wrapper.displayName = `AnimationWrapper(${WrappedComponent.displayName | WrappedComponent.name | 'Component'})`;
return Wrapper;
};
const Line = ({ data }) => (
<polyline
fill="none"
stroke="#0074d9"
strokeWidth="2"
points={data}
/>
);
const AnimatedLine = animateLine(Line);
const SvgThing = ({ data }) => (
<svg viewBox="0 0 500 100">
<AnimatedLine
data={data}
xSelector={(d) => d.x}
ySelector={(d) => d.y} />
</svg>
);
let randomChartData = [];
for (let i = 0; i < 46; i++) {
randomChartData.push({ y: Math.floor(120 - Math.random() * (120 - 0)), x: i * 20 });
}
ReactDOM.render(<SvgThing data={randomChartData} />, document.getElementById('svg-demo'));
})();