← Blurr Motion form-physics-feedback-playful
Categorie forms Tier 2 Techniek #31 Deps matter-js, gsap
1. Mechanisme — kopieer 1-op-1, geen styling-keuzes
// Mechanisme: form-physics-feedback-playful
import gsap from 'https://esm.sh/gsap@3.12.5';
import Matter from 'https://esm.sh/matter-js@0.20.0';
const reduce=window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const form=document.querySelector('.physics-form');
const cv=document.querySelector('.physics-canvas');
const fb=document.querySelector('.physics-fallback');
if(!form||!cv)return;
form.querySelectorAll('input,textarea').forEach(i=>{
  i.addEventListener('focus',()=>gsap.to(i,{scale:1.02,duration:0.5,ease:'back.out(1.7)'}));
  i.addEventListener('blur',()=>gsap.to(i,{scale:1,duration:0.5,ease:'back.out(1.7)'}));
});
form.addEventListener('submit',e=>{
  e.preventDefault();
  if(reduce){fb.style.display='flex';gsap.fromTo(fb,{opacity:0,scale:0.8},{opacity:1,scale:1,duration:0.4});return;}
  const r=cv.getBoundingClientRect();const W=r.width,H=r.height;
  const{Engine,Render,Runner,Bodies,Composite}=Matter;
  const eng=Engine.create();eng.world.gravity.y=1;
  const rend=Render.create({canvas:cv,engine:eng,options:{width:W,height:H,wireframes:false,background:'transparent'}});
  Composite.add(eng.world,[
    Bodies.rectangle(W/2,H+10,W,20,{isStatic:true,render:{visible:false}}),
    Bodies.rectangle(-10,H/2,20,H,{isStatic:true,render:{visible:false}}),
    Bodies.rectangle(W+10,H/2,20,H,{isStatic:true,render:{visible:false}})
  ]);
  const colors=['#FF4A1C','#FFB5A7','#F4F1EB'];
  for(let i=0;i<24;i++){
    setTimeout(()=>{
      Composite.add(eng.world,Bodies.circle(W/2+(Math.random()-0.5)*40,-20,8+Math.random()*8,{
        restitution:0.75,friction:0.02,
        render:{fillStyle:colors[i%3]}
      }));
    },i*60);
  }
  Render.run(rend);Runner.run(Runner.create(),eng);
});
2. Skeleton — DOM + class-namen, mag herschikken
<!-- Skeleton: form-physics-feedback-playful -->
<div class="demo-block">
  <form class="physics-form">
    <input type="text" placeholder="Naam"/>
    <input type="email" placeholder="Email"/>
    <textarea placeholder="Bericht"></textarea>
    <button type="submit">Verstuur</button>
  </form>
  <canvas class="physics-canvas"></canvas>
  <div class="physics-fallback">Bedankt!</div>
</div>
3. Styling-template — verplicht eigen invulling per merk
/* Styling: form-physics-feedback-playful */
:root {
  --block-bg: #F4F1EB;
  --block-fg: #0A0A0A;
  --block-accent: #FF4A1C;
  --block-accent-soft: #FFB5A7;
}
.physics-form input, .physics-form textarea {
  border-radius: 14px;
  font-family: 'Archivo', sans-serif;
  font-weight: 500;
  transition: border-color .3s;
}
.physics-form button {
  border-radius: 999px;
  font-family: 'Archivo', sans-serif;
  font-weight: 500;
}
@media (prefers-reduced-motion: reduce) {
  .physics-canvas { display: none; }
}