Ballon die opstijgt Nieuw
Op de bedankpagina na een bestelling hangt een ballon aan een touwtje met een gewichtje; laat hem los (knop of klik op de ballon) en hij stijgt op met opwaartse kracht, deint in de wind en sleept zijn touwtje mee. Daarna zegt de pagina wanneer de bezorger komt en blaas je een nieuwe ballon op. Voor de bedankpagina van een webshop, een jubileum of een feestelijke aankondiging. Bij minder beweging verdwijnt de ballon direct en verschijnt de bezorgtijd.
Bedankt voor je bestelling
Order 10482 gaat morgen naar Haarlem. Laat de ballon maar los.
Zo gebruik je het
- Plak de HTML op de plek waar het onderdeel moet komen.
- Zet de CSS in je stylesheet. Alle klassen hebben een eigen voorvoegsel, dus niets botst met je eigen opmaak.
- Voeg de JavaScript toe en roep init() aan met het element waar de HTML in staat.
<!-- Ballon die opstijgt · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie -->
<div class="jouw-container">
<div class="fyl">
<div class="fyl__tekst">
<h3 class="fyl__h">Bedankt voor je bestelling</h3>
<p class="fyl__p">Order 10482 gaat morgen naar Haarlem. Laat de ballon maar los.</p>
<button class="fyl__knop" type="button">Laat de ballon los</button>
<p class="fyl__code" aria-live="polite"></p>
</div>
<svg class="fyl__touw" aria-hidden="true"><path d=""/></svg>
<span class="fyl__gewicht" aria-hidden="true"></span>
<div class="fyl__ballon" aria-hidden="true"><svg viewBox="0 0 100 124"><path class="fyl__vorm" d="M50 2C79 2 98 25 98 52C98 81 72 104 50 108C28 104 2 81 2 52C2 25 21 2 50 2Z"/><path class="fyl__knoop" d="M43 117L50 106L57 117Z"/><ellipse class="fyl__licht" cx="30" cy="30" rx="9" ry="15" transform="rotate(25 30 30)"/></svg><span class="fyl__t">Bedankt</span></div>
</div>
</div>/* Ballon die opstijgt · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie */
.fyl{position:absolute;inset:0;overflow:hidden;background:#f4f3f1;color:#0a0a0a;font-family:'Switzer',sans-serif;text-align:left}
.fyl *{box-sizing:border-box}
.fyl__tekst{position:absolute;left:16px;top:50%;transform:translateY(-50%);width:54%;display:flex;flex-direction:column;align-items:flex-start;gap:6px;z-index:2}
.fyl__h{margin:0;font:700 18px/1.15 'Switzer',sans-serif;letter-spacing:-.015em}
.fyl__p{margin:0;font:400 13px/1.4 'Switzer',sans-serif;color:#3d3b37}
.fyl__knop{margin-top:2px;padding:9px 13px;border:0;border-radius:4px;background:#0a0a0a;color:#fff;font:600 13px/1 'Switzer',sans-serif;cursor:pointer;transition:background-color .16s,color .16s}
.fyl__knop:hover{background:#F5480F;color:#0a0a0a}
.fyl__knop:focus-visible{outline:2px solid #F5480F;outline-offset:2px}
.fyl__code{margin:0;min-height:18px;font:600 13px/1.35 'Switzer',sans-serif}
.fyl__touw{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
.fyl__touw path{fill:none;stroke:#0a0a0a;stroke-width:1.2;stroke-linecap:round}
.fyl__gewicht{position:absolute;left:0;top:0;width:14px;height:10px;border-radius:2px;background:#0a0a0a}
.fyl__ballon{position:absolute;left:0;top:0;width:84px;cursor:pointer;transform-origin:50% 90%;will-change:transform}
.fyl__ballon svg{display:block;width:100%;height:auto}
.fyl__vorm,.fyl__knoop{fill:#F5480F}
.fyl__licht{fill:#fff;opacity:.28}
.fyl__t{position:absolute;left:0;right:0;top:30%;text-align:center;font:800 22px/1 'Switzer',sans-serif;color:#0a0a0a;pointer-events:none}// Ballon die opstijgt · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie
// root = het element waarin de HTML staat
function init(root){
var el=root.querySelector('.fyl');if(!el)return;
var RM=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;
var bal=el.querySelector('.fyl__ballon'),touw=el.querySelector('.fyl__touw'),pad=touw.querySelector('path'),gew=el.querySelector('.fyl__gewicht'),knop=el.querySelector('.fyl__knop'),code=el.querySelector('.fyl__code'),txt=bal.querySelector('.fyl__t');
var W=1,H=1,bw=84,bh=104,rx=0,ry=0,x=0,y=0,vx=0,vy=0,sc=1,vs=0,modus='vast',N=10,P=[],seg=8,gx=0,gy=0,raf=0,last=0,vis=true,tijd=0,DT=1/60,acc=0;
function maat(){var r=el.getBoundingClientRect();if(!r.width)return false;W=r.width;H=r.height;bw=Math.max(66,Math.min(96,H*.36));bh=bw*1.24;bal.style.width=bw.toFixed(1)+'px';txt.style.fontSize=Math.max(13,bw*.16).toFixed(1)+'px';
touw.setAttribute('viewBox','0 0 '+W.toFixed(1)+' '+H.toFixed(1));rx=W*.77;ry=H*.08;gx=rx-4;gy=H-14;gew.style.transform='translate('+(gx-7).toFixed(1)+'px,'+gy.toFixed(1)+'px)';return true;}
function nieuwTouw(){var kx=x+bw/2,ky=y+bh*.94,L=Math.hypot(gx-kx,gy-ky)+8;seg=L/N;P=[];for(var i=0;i<=N;i++){var u=i/N,px=kx+(gx-kx)*u,py=ky+(gy-ky)*u;P.push({x:px,y:py,px:px,py:py});}}
function teken(){bal.style.transform='translate('+x.toFixed(1)+'px,'+y.toFixed(1)+'px) rotate('+Math.max(-14,Math.min(14,vx*.05)).toFixed(2)+'deg) scale('+sc.toFixed(3)+')';
var d='M'+P[0].x.toFixed(1)+' '+P[0].y.toFixed(1);for(var i=1;i<P.length;i++)d+=' L'+P[i].x.toFixed(1)+' '+P[i].y.toFixed(1);pad.setAttribute('d',d);}
function stap(){tijd+=DT;var i,p;
if(modus==='vast'){var dx=rx+Math.sin(tijd*.9)*W*.025+Math.sin(tijd*2.1)*W*.01-bw/2,dy=ry+Math.sin(tijd*1.4)*4;vx+=((dx-x)*7-vx*2.2)*DT;vy+=((dy-y)*7-vy*2.2)*DT;}
else if(modus==='los'){vy+=-560*DT;vx+=Math.sin(tijd*2.3)*90*DT;vx*=.992;vy*=.996;}
x+=vx*DT;y+=vy*DT;vs+=((1-sc)*260-vs*13)*DT;sc+=vs*DT;
P[0].x=x+bw/2;P[0].y=y+bh*.94*sc+bh*.06;P[0].px=P[0].x;P[0].py=P[0].y;
for(i=1;i<P.length;i++){p=P[i];if(i===N&&modus!=='los'){p.x=gx;p.y=gy;p.px=gx;p.py=gy;continue;}var ux=(p.x-p.px)*.98,uy=(p.y-p.py)*.98;p.px=p.x;p.py=p.y;p.x+=ux;p.y+=uy+380*DT*DT;}
for(var it=0;it<10;it++)for(i=0;i<N;i++){var a=P[i],b=P[i+1],ex=b.x-a.x,ey=b.y-a.y,d=Math.sqrt(ex*ex+ey*ey)||.001;if(d<=seg&&modus!=='los')continue;
var f=(d-seg)/d,wa=i===0?0:.5,wb=(i+1===N&&modus!=='los')?0:.5,s=wa+wb;if(!s)continue;a.x+=ex*f*wa/s;a.y+=ey*f*wa/s;b.x-=ex*f*wb/s;b.y-=ey*f*wb/s;}
if(modus==='los'){if(y+bh<-20&&P[N].y<-10){modus='weg';bal.style.visibility='hidden';pad.setAttribute('d','');toonCode();}}}
function tick(t){if(!vis){raf=0;return;}acc+=Math.min(.05,(t-(tick.l||t))/1000);tick.l=t;while(acc>=DT){stap();acc-=DT;}if(modus!=='weg')teken();raf=modus==='weg'?0:requestAnimationFrame(tick);if(!raf)tick.l=0;}
function kick(){if(RM||raf)return;tick.l=0;acc=0;raf=requestAnimationFrame(tick);}
function toonCode(){code.textContent='Morgen tussen 10:00 en 13:00 staat de bezorger bij je voor de deur.';knop.textContent='Nieuwe ballon';}
function laatLos(){if(modus==='vast'){if(RM){modus='weg';bal.style.visibility='hidden';pad.setAttribute('d','');toonCode();return;}modus='los';vy=-40;knop.textContent='Daar gaat hij';kick();}
else if(modus==='weg'){modus='vast';x=rx-bw/2;y=ry+20;vx=vy=0;bal.style.visibility='';nieuwTouw();knop.textContent='Laat de ballon los';if(RM){sc=1;teken();return;}sc=.25;vs=0;kick();}}
knop.addEventListener('click',laatLos);bal.addEventListener('click',function(){if(modus==='vast')laatLos();});
if(maat()){x=rx-bw/2;y=ry;nieuwTouw();teken();kick();}
if('ResizeObserver' in window)new ResizeObserver(function(){if(maat()&&modus==='vast'){x=rx-bw/2;y=ry;nieuwTouw();teken();}}).observe(el);
if('IntersectionObserver' in window)new IntersectionObserver(function(es){vis=es[0].isIntersecting;if(vis&&modus!=='weg')kick();}).observe(el);
}
init(document.querySelector('.jouw-container'));
Meer uit componenten
Iets gezien dat je mooi vindt?
Zet het in je selectie en stuur hem op. Dan bouwen we je site eromheen, in jouw huisstijl.
Neem contact op →