Skip to content

Instantly share code, notes, and snippets.

@vasturiano
Last active April 20, 2017 19:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vasturiano/351c45c55db3f997b8d8ca30447ac0a3 to your computer and use it in GitHub Desktop.
Save vasturiano/351c45c55db3f997b8d8ca30447ac0a3 to your computer and use it in GitHub Desktop.
React + D3
license: mit

An example of a React component integrated with D3.

<head>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/4.7.0/d3.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-dom.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.23.1/babel.min.js"></script>
<script type="text/jsx" src="react-d3-comp.jsx"></script>
</head>
<body>
<div id="myElem"></div>
<script type="text/jsx">
ReactDOM.render(<D3Comp/>, document.getElementById('myElem'));
</script>
</body>
class D3Comp extends React.Component {
constructor(props) {
super(props);
// Consts
this.ANIMATION_DURATION = 1000; // ms
this.REACT_LOGO = '<g transform="scale(0.07)" fill="#00D8FF"><circle class="st0" cx="299.5" cy="299.6" r="50.2"/><g><path class="st0" d="M299.5,414.6c-70.5,0-132.1-8.3-178.2-24.1c-29.9-10.2-55.3-23.8-73.4-39.3c-19.2-16.4-29.4-34.3-29.4-51.6 c0-33.2,36.4-65.7,97.5-86.9c50-17.4,115.2-27.1,183.4-27.1c67,0,131.3,9.4,181,26.6c29.1,10,53.6,23,71,37.4 c18.9,15.8,28.9,33.1,28.9,50c0,34.5-40.7,69.4-106.3,91.1C427.6,406.1,365.6,414.6,299.5,414.6z M299.5,209.6 c-64.7,0-128.7,9.4-175.5,25.7c-56.2,19.6-81.4,46.4-81.4,64.3c0,18.6,27.1,47.9,86.5,68.2c43.6,14.9,102.6,22.8,170.4,22.8 c63.6,0,122.9-8,167-22.7c61.7-20.5,89.9-49.8,89.9-68.3c0-9.5-7.2-20.7-20.3-31.6c-15.1-12.6-37.1-24.1-63.4-33.2 C425.4,218.6,363.9,209.6,299.5,209.6z"/></g><g><path class="st0" d="M185.6,549.8c-10.2,0-19.2-2.2-26.8-6.6c-28.7-16.6-38.7-64.4-26.6-127.9c9.9-52.1,34.1-113.3,68.2-172.4 c33.5-58,73.7-109,113.4-143.5c23.2-20.2,46.7-35,67.9-42.8c23.1-8.5,43.1-8.5,57.7-0.1c29.9,17.2,39.8,70,25.8,137.6 c-9.9,48-33.5,105.9-66.5,163.2c-35.2,61-73.2,110.2-109.9,142.3c-23.8,20.8-48.3,36-70.7,43.9 C206.4,547.7,195.4,549.8,185.6,549.8z M210.7,248.9l10.4,6c-32.3,56-56.2,116.1-65.4,164.9c-11.1,58.5-0.4,93.7,15,102.6 c3.8,2.2,8.8,3.4,14.9,3.4c19.9,0,51.2-12.6,87.4-44.2c34.7-30.3,71-77.5,104.9-136.2c31.8-55.1,54.4-110.5,63.8-156 c13.1-63.7,1.8-102.7-14.3-112c-8.2-4.7-21.5-4.1-37.5,1.8c-18.5,6.8-39.4,20.1-60.4,38.4c-37.7,32.8-76.2,81.6-108.4,137.4 L210.7,248.9z"/></g><g><path class="st0" d="M413.4,550.1c-27.2,0-61.7-16.4-97.7-47.4c-40.2-34.6-81.1-86.1-115.3-145.2v0c-33.6-58-57.6-118.3-67.7-170 c-5.9-30.2-7-57.9-3.2-80.2c4.2-24.3,14.1-41.6,28.8-50.1c29.8-17.3,80.5,0.5,132.1,46.4c36.6,32.5,75,81.9,108.1,139.1 c35.3,61,59,118.5,68.4,166.3c6.1,31,7.1,59.8,2.8,83.2c-4.6,24.9-15,42.6-30,51.3C432.2,547.9,423.3,550.1,413.4,550.1z M221.2,345.5c32.4,56,72.6,106.7,110.2,139c45.1,38.8,80.9,47.2,96.4,38.2c16.1-9.3,27.9-47.4,15.7-109 c-9-45.2-31.7-100.2-65.7-158.9c-31.9-55.1-68.6-102.4-103.3-133.2C225.9,78.4,186.5,68.7,170.4,78c-8.2,4.7-14.3,16.6-17.2,33.4 c-3.3,19.4-2.3,44.2,3.1,71.5C165.9,232,188.9,289.7,221.2,345.5L221.2,345.5z"/></g></g>';
this.D3_LOGO = '<g transform="scale(0.7)"><linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="13.7053" y1="30.619" x2="35.156" y2="9.1684" gradientTransform="matrix(1 0 0 -1 0 35)"><stop offset="0" style="stop-color:#F9A13E"/><stop offset="1" style="stop-color:#F89850"/></linearGradient><path fill="url(#SVGID_1_)" d="M34.4,25.2c0-0.1,0-0.3,0-0.4c0-0.2-10.7-10.3-10.7-10.3h-0.3C23.5,14.4,34.3,25.8,34.4,25.2z"/><linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="-2.2899" y1="27.0299" x2="16.7014" y2="8.0385" gradientTransform="matrix(1 0 0 -1 0 35)"><stop offset="0" style="stop-color:#F9A13E"/><stop offset="1" style="stop-color:#F89850"/></linearGradient><path fill="url(#SVGID_2_)" d="M11.6,21.6C11.6,21.7,11.6,21.7,11.6,21.6c-0.1,0.1-0.1,0.2-0.1,0.2c-0.3,0.7,4.8,5.7,5.2,5.1c0,0,0-0.1,0.1-0.1c0,0,0-0.1,0.1-0.1C17.1,26.2,11.8,21.3,11.6,21.6z"/><linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="4.7648" y1="20.1995" x2="24.0016" y2="0.9628" gradientTransform="matrix(1 0 0 -1 0 35)"><stop offset="0" style="stop-color:#F9A13E"/><stop offset="1" style="stop-color:#F89850"/></linearGradient><path fill="url(#SVGID_3_)" d="M18.8,28.7c0,0-0.1,0.2-0.2,0.3c0,0,5,5,5,5H24C24,33.9,19.4,28.9,18.8,28.7z"/><linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="1.1339" y1="33.695" x2="31.2463" y2="3.5826" gradientTransform="matrix(1 0 0 -1 0 35)"><stop offset="0" style="stop-color:#F16D59"/><stop offset="1" style="stop-color:#F9A13E"/></linearGradient><path fill="url(#SVGID_4_)" d="M34.4,24.6c-0.2,5.2-4.5,9.3-9.8,9.3H24l-5.2-5.2c0.4-0.6,0.8-1.2,1.2-1.9h4.8c1.5,0,2.7-1.2,2.7-2.7c0-1.5-1.2-2.7-2.7-2.7h-2.8c0.2-1.1,0.3-2.3,0.3-3.5c0-1.2-0.1-2.4-0.3-3.6h1.7L34.4,25C34.4,24.9,34.4,24.8,34.4,24.6z M3.4,1.9H0.5v7h2.8c5,0,9,4,9,9c0,1.4-0.3,2.6-0.8,3.8l5.2,5.1c1.7-2.5,2.7-5.6,2.7-8.9C19.5,9.1,12.2,1.9,3.4,1.9z"/><linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="16.5319" y1="36.4841" x2="38.7353" y2="14.2808" gradientTransform="matrix(1 0 0 -1 0 35)"><stop offset="0" style="stop-color:#B94E52"/><stop offset="1" style="stop-color:#F68E4A"/></linearGradient><path fill="url(#SVGID_5_)" d="M24.7,1.9H13.2c2.8,1.7,5.1,4.2,6.7,7h4.8c1.5,0,2.7,1.2,2.7,2.7c0,1.5-1.2,2.7-2.7,2.7h-1.1L34.4,25c0-0.3,0-0.6,0-0.9c0-2.4-0.9-4.6-2.3-6.3c1.4-1.7,2.3-3.9,2.3-6.3C34.5,6.3,30.1,1.9,24.7,1.9z"/><linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="2.8927" y1="10.391" x2="18.0983" y2="-4.8146" gradientTransform="matrix(1 0 0 -1 0 35)"><stop offset="0" style="stop-color:#F9A13E"/><stop offset="1" style="stop-color:#F89850"/></linearGradient><path fill="url(#SVGID_6_)" d="M24,33.9H13.2c2.2-1.3,4-3.1,5.5-5.2L24,33.9z M16.8,26.8l-5.2-5.1C10.1,24.8,7,27,3.4,27H0.5v7h2.8C9,34,13.9,31.2,16.8,26.8z"/></g>';
// Initialize state
this.state = {
width: window.innerWidth,
height: window.innerHeight,
xyData: this._getRandomXYData()
};
this._d3Digest = this._d3Digest.bind(this);
}
componentDidMount() {
setInterval(() => this.setState({ xyData: this._getRandomXYData() }), this.ANIMATION_DURATION + 100); // Force update
this._d3Digest(); // Init
}
componentDidUpdate(prevProps, prevState) {
this._d3Digest();
}
render() {
return <svg
ref = { elem => { this.canvas = elem }}
width = {this.state.width}
height = {this.state.height}
/>;
}
_d3Digest() {
let logos = d3.select(this.canvas)
.selectAll('.logo')
.data(this.state.xyData);
logos.exit()
.transition().duration(this.ANIMATION_DURATION)
.style('opacity', 0)
.remove();
logos.merge(
logos.enter()
.append('g')
.classed('logo', true)
.style('opacity', 0)
.attr('transform', `translate(${this.state.width/2},${this.state.height/2})`) // Init on center
.html(() => [this.REACT_LOGO, this.D3_LOGO][Math.floor(Math.random()*2)])
).transition().duration(this.ANIMATION_DURATION)
.style('opacity', 1)
.attr('transform', d => `translate(${this.state.width * d[0]},${this.state.height * d[1]})`);
}
_getRandomXYData() {
return d3.range(Math.round(Math.random() * 100)).map(() => [Math.random(), Math.random()]);
}
}
D3Comp.propTypes = {};
D3Comp.defaultProps = {};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment