Skip to content

Instantly share code, notes, and snippets.

@larsvers
Last active October 24, 2016 09:57
Show Gist options
  • Save larsvers/c7d6ed2978ac5bd6dd1097c858190269 to your computer and use it in GitHub Desktop.
Save larsvers/c7d6ed2978ac5bd6dd1097c858190269 to your computer and use it in GitHub Desktop.
mnml goo
license: mit
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
</style>
</head>
<body>
<div id="container"></div>
<script>
var margin = { top: 50, right: 50, bottom: 50, left: 50 },
width = 1000 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var svg = d3.select('#container')
.append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
.attr('filter', 'url(#goo)'); // goo needs to be attached to parent object
// add the defs
var defs = svg.append('defs');
var filter = defs.append('filter').attr('id','goo');
filter.append('feGaussianBlur')
.attr('in','SourceGraphic')
.attr('stdDeviation','15')
.attr('result','blur');
filter.append('feColorMatrix')
.attr('in','blur')
.attr('mode','matrix')
.attr('values','1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 25 -9')
.attr('result','goo');
// both optional for circles
// this is necessary for squares
// filter.append('feComposite')
// .attr('in','SourceGraphic')
// .attr('in2','goo')
// .attr('operator','atop');
// or this, which seems unnecessary for circles and allows for nicer colour-merging
// filter.append('feBlend')
// .attr('in','SourceGraphic')
// .attr('in2','goo');
svg.append('circle')
.attr('class', 'circleCenter')
.attr('cx', width/2)
.attr('cy', height/2)
.attr('r', 40)
.style('fill', 'tomato');
svg.append('circle')
.attr('class', 'circleFly')
.attr('cx', width/2)
.attr('cy', height/2)
.attr('r', 40)
.style('fill', 'tomato')
.transition()
.on('start', repeat);
var ease = d3.easeCubic;
function repeat() {
var coords = randCoord(200,150) ;
d3.active(this) // returns the active transition on this node, which will always be the latest as the node listener triggers this function continuously
.attr('cx', width/2)
.attr('cy', height/2)
.attr('r', 40) // reset position
.transition().duration(1000).ease(ease)
.attr('cx', width/2 + coords[0])
.attr('cy', height/2 + coords[1])
.attr('r', 20) // transition to this
.transition().duration(1000).ease(ease)
.on('start', repeat); // kickstart process
} // repeat()
function randCoord(x,y) {
x = Math.round(Math.random()) ? - Math.floor((Math.random()) * x) : Math.floor((Math.random()) * x);
y = Math.round(Math.random()) ? - Math.floor((Math.random()) * y) : Math.floor((Math.random()) * y);
return [x,y];
} // takes 2 maximum limits by which we want the bubbles to fly off and returns a randomised distance
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment