Metaball Blob Field
Liquid metaballs that merge and follow the cursor.
How to use it
- Paste the HTML where the backgrounds & webgl should appear. Include the script tags at the top once per page.
- Add the CSS to your stylesheet. All classes are prefixed, so nothing clashes with your own styles.
- Add the JavaScript and call init() with the element that contains the HTML.
<!-- Metaball Blob Field · NedDev · eigen werk. -->
<!-- benodigd, één keer per pagina: -->
<script type="module">import * as OGL from "https://esm.sh/ogl@1.0.11"; window.OGL = OGL;</script>
<div class="jouw-container">
</div>/* Metaball Blob Field · NedDev · eigen werk. */
.mb-stage{position:relative;width:100%;height:100%;background:#0a0a0a;overflow:hidden}.mb-stage canvas{position:absolute;inset:0;width:100%;height:100%;display:block;filter:contrast(18) blur(.3px)}// Metaball Blob Field · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
root.classList.add('mb-stage');var reduce=matchMedia('(prefers-reduced-motion:reduce)').matches;var c=document.createElement('canvas');root.appendChild(c);var ctx=c.getContext('2d');var W=0,H=0,dpr=Math.min(devicePixelRatio||1,1.5),run=false,t=0;var N=6,blobs=[];
function size(){var r=root.getBoundingClientRect();W=r.width;H=r.height;c.width=W*dpr;c.height=H*dpr;ctx.setTransform(dpr,0,0,dpr,0,0);}new ResizeObserver(size).observe(root);size();
for(var i=0;i<N;i++)blobs.push({r:34+Math.random()*30,sp:.3+Math.random()*.5,rad:.18+Math.random()*.22,ph:Math.random()*7});
var mouse={x:.5,y:.5,active:false};root.addEventListener('pointermove',function(e){var r=root.getBoundingClientRect();mouse.x=(e.clientX-r.left)/W;mouse.y=(e.clientY-r.top)/H;mouse.active=true;});root.addEventListener('pointerleave',function(){mouse.active=false;});
function draw(){if(!run)return;t+=reduce?0:.01;ctx.clearRect(0,0,W,H);ctx.globalCompositeOperation='lighter';for(var i=0;i<N;i++){var b=blobs[i];var x=(.5+Math.cos(t*b.sp+b.ph)*b.rad)*W;var y=(.5+Math.sin(t*b.sp*1.3+b.ph)*b.rad)*H;if(mouse.active&&i<2){x=mouse.x*W;y=mouse.y*H;}var g=ctx.createRadialGradient(x,y,0,x,y,b.r);g.addColorStop(0,'rgba(245,72,15,1)');g.addColorStop(.6,'rgba(245,72,15,.5)');g.addColorStop(1,'rgba(245,72,15,0)');ctx.fillStyle=g;ctx.beginPath();ctx.arc(x,y,b.r,0,7);ctx.fill();}ctx.globalCompositeOperation='source-over';if(!reduce)requestAnimationFrame(draw);}
new IntersectionObserver(function(es){var v=es[0].isIntersecting;if(v&&!run){run=true;requestAnimationFrame(draw);}else if(!v)run=false;}).observe(root);if(reduce){run=true;draw();run=false;}
}
init(document.querySelector('.jouw-container'));
More backgrounds & webgl
Seen something you like?
Add it to your selection and send it over. We build your site around it, in your brand.
Get in touch →