Skip to content

Instantly share code, notes, and snippets.

@milroc
Last active June 5, 2016 22:01
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 milroc/b5ec7dda906e52616300064bc0ceaafd to your computer and use it in GitHub Desktop.
Save milroc/b5ec7dda906e52616300064bc0ceaafd to your computer and use it in GitHub Desktop.
GooeySpinner Trippy (React + d3)

I had wanted to play with the Gooey Effect for some time. I decided to use React for this so I rewrote some of the code from the below forks.

Once the rewrite was complete, I played with some numbers and found this interesting aesthetic effect. The spinner I think is rather compelling. Would probably do a couple more iterations on it before I considered using it in a product though.

The things that are important to take note of in the rewrite is how you use could refs to manage what portion of the UI is handled with d3 and what is managed with React.

--

forked from sxywu's block: Gooey Circle Effect with Colors

forked from nbremer's block: Gooey Effect - Circle

forked from sxywu's block: GooeySpinner (React + d3)

forked from milroc's block: GooeySpinner (React + d3)

<!DOCTYPE html>
<meta charset="utf-8">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script>
<script src="https://npmcdn.com/babel-core@5.8.34/browser.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>
</head>
<body>
<div id="main" />
<script type="text/babel">
function endall(transition, callback) {
let n = 0;
transition
.each(function() { ++n; })
.each('end', function() { if (!--n) callback.apply(this, arguments); });
}// endall
// Number of clocks on the page
let spinnerCounter = 0;
class GooeySpinner extends React.Component {
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} height={height}>
<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}, ${height/2})`}>
<circle
className="centerCircle"
cx={0}
cy={0}
r={4}
fill="#513700"
/>
<g ref="flyCircles" />
</g>
</svg>
</div>
);
}
}
GooeySpinner.defaultProps = {
width: 60,
height: 60,
steps: 12,
color: [
'#a50026', '#d73027', '#f46d43',
'#fdae61', '#fee08b',
'#d9ef8b', '#a6d96a', '#66bd63',
'#1a9850', '#006768', '#00425d',
],
};
class App extends React.Component {
render() {
return (
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'flexstart',
flexWrap: 'wrap',
}}>
{d3.range(16*9).map((key) => <GooeySpinner key={key} />)}
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('main')
);
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment