block by milroc 15f8046a7ce5e8a9730f6109d66745ce

fresh block

Full Screen

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

index.html

<!DOCTYPE html>
<script src="https://jspm.io/system@0.19.js"></script>
<script>
System.config({
  transpiler: 'babel',
  babelOptions: {}
});
System.import('./main');
</script>

endall.js

// 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

main.js

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"))
);