Built with blockbuilder.org
forked from anonymous's block: fresh block
forked from anonymous's block: fresh block
forked from anonymous's block: fresh block
Built with blockbuilder.org
forked from anonymous's block: fresh block
forked from anonymous's block: fresh block
forked from anonymous's block: fresh block
| // Taken from https://groups.google.com/forum/#!msg/d3-js/WC_7Xi6VV50/j1HK0vIWI-EJ | |
| // Calls a function only after the total transition ends | |
| export default function endall(transition, callback) { | |
| let n = 0; | |
| transition | |
| .each(function() { ++n; }) | |
| .each('end', function() { if (!--n) callback.apply(this, arguments); }); | |
| }// endall |
| <!DOCTYPE html> | |
| <script src="https://jspm.io/[email protected]"></script> | |
| <script> | |
| System.config({ | |
| transpiler: 'babel', | |
| babelOptions: {} | |
| }); | |
| System.import('./main'); | |
| </script> |
| import React from 'react'; | |
| import ReactDOM from 'react-dom'; | |
| import d3 from 'd3'; | |
| import endall from './endall'; | |
| // Number of clocks on the page | |
| let spinnerCounter = 0; | |
| class GooeySpinner extends React.Component { | |
| static defaultProps = { | |
| width: 60, | |
| height: 60, | |
| margin: {top: 0, right: 0, bottom: 0, left: 0}, | |
| steps: 12, | |
| color: [ | |
| '#a50026', '#d73027', '#f46d43', | |
| '#fdae61', '#fee08b', | |
| '#d9ef8b', '#a6d96a', '#66bd63', | |
| '#1a9850', '#006768', '#00425d', | |
| ], | |
| }; | |
| constructor(props) { | |
| super(props); | |
| this.spinnerID = spinnerCounter++; | |
| this._repeat = this._repeat.bind(this); | |
| this._getFilterID = this._getFilterID.bind(this); | |
| } | |
| componentDidMount() { | |
| const {width, steps, color} = this.props; | |
| // Create scale | |
| this.radialScale = d3.scale.linear() | |
| .domain([-1.5, 1.5]) | |
| .range([-width/2, width/2]); | |
| // color from http://colrd.com/palette/24070/ | |
| this.colorScale = d3.scale.ordinal().range(color); | |
| this._flyCirclesContainer = d3.select(ReactDOM.findDOMNode(this.refs.flyCircles)); | |
| this._flyCircles = this._flyCirclesContainer.selectAll('.flyCircle') | |
| .data(d3.range(steps).map((num) => (num / steps ) * (2 * Math.PI))); | |
| this._flyCircles.enter() | |
| .append('circle') | |
| .attr({ | |
| class: 'flyCircle', | |
| cx: 0, | |
| cy: 0, | |
| r: 4, | |
| }) | |
| .style('fill', (d, i) => this.colorScale(i)) | |
| .call(this._repeat); | |
| } | |
| _repeat() { | |
| const {steps} = this.props; | |
| const dur = 1000; | |
| const del = 100; | |
| this._flyCircles | |
| .transition('outward') | |
| .duration(dur) | |
| .delay((_,i) => i * del) | |
| .attr({ | |
| cx: (d) => this.radialScale(Math.cos(d)), | |
| cy: (d) => this.radialScale(Math.sin(d)), | |
| }) | |
| .transition('inward') | |
| .duration(dur) | |
| .delay((d,i) => (steps * 1.2) * del + i * del) | |
| .attr('cx', 0) | |
| .attr('cy', 0) | |
| .call(endall, this._repeat); | |
| } | |
| _getFilterID() { | |
| return `gooey-${this.spinnerID}`; | |
| } | |
| render() { | |
| const {width, height, margin} = this.props; | |
| return ( | |
| <div> | |
| <svg | |
| width={width + margin.left + margin.right} | |
| height={height + margin.top + margin.bottom}> | |
| <defs> | |
| <filter id={this._getFilterID()}> | |
| <feGaussianBlur | |
| in="SourceGraphic" | |
| stdDeviation={4} | |
| result="blur" | |
| /> | |
| <feColorMatrix | |
| in="blur" | |
| mode="matrix" | |
| values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 18 -7" | |
| /> | |
| </filter> | |
| </defs> | |
| <g | |
| filter={`url(#${this._getFilterID()})`} | |
| transform={`translate(${width/2 + margin.left}, ${height/2 + margin.top})`}> | |
| <circle | |
| className="centerCircle" | |
| cx={0} | |
| cy={0} | |
| r={4} | |
| fill="#ffffbf" | |
| /> | |
| <g ref="flyCircles" /> | |
| </g> | |
| </svg> | |
| </div> | |
| ); | |
| } | |
| } | |
| class App extends React.Component { | |
| render() { | |
| return ( | |
| <div style={{ | |
| display: 'flex', | |
| justifyContent: 'center', | |
| alignItems: 'flexstart', | |
| }}> | |
| {[0].map((i) => ( | |
| <GooeyClock key={i} steps={12} /> | |
| ))} | |
| </div> | |
| ); | |
| } | |
| } | |
| ReactDOM.render( | |
| <App />, | |
| document.body.appendChild(document.createElement("div")) | |
| ); |