Simple gooey effect with 2 circles.
All stolen from Lucas Bebber's post and Nadieh Bremer's post(s) and translated to V4 (phew)...
Built with blockbuilder.org
| license: mit |
Simple gooey effect with 2 circles.
All stolen from Lucas Bebber's post and Nadieh Bremer's post(s) and translated to V4 (phew)...
Built with blockbuilder.org
| <!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> |