Motion Lab / Forms / shader success / kinetic
// Mechanisme: form-shader-success-kinetic (techniek #36 — custom GLSL fragment shader)
// Bij submit toont een WebGL2-canvas met kleurrijke plasma/wave (#FF4A1C accent).
// Auto-demo elke 3s. Reduced-motion: single render (geen animation loop).
const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const canvas = document.querySelector('.shader-canvas');
const overlay = document.querySelector('.kinetic-overlay');
const form = document.querySelector('.kinetic-form');
const gl = canvas && canvas.getContext('webgl2');
const VS = '#version 300 es\nin vec2 p;void main(){gl_Position=vec4(p,0.,1.);}';
const FS = `#version 300 es
precision highp float;
out vec4 o;
uniform vec2 r;
uniform float t;
void main(){
vec2 uv = (gl_FragCoord.xy - 0.5 * r) / min(r.x, r.y);
float d = length(uv);
float w = sin(d * 22.0 - t * 6.0) * 0.5 + 0.5;
w *= smoothstep(0.95, 0.0, d);
vec3 hot = vec3(1.0, 0.29, 0.11);
vec3 dark = vec3(0.039);
vec3 paper = vec3(0.957, 0.945, 0.922);
o = vec4(mix(dark, mix(paper, hot, w), w * 0.9), 1.0);
}`;
// Compile + link, set up fullscreen quad, animate t. Bij submit: overlay.classList.add('on'). <!-- Skeleton: form-shader-success-kinetic -->
<div class="kinetic-wrap">
<form class="kinetic-form" onsubmit="event.preventDefault()">
<div class="field"><input type="text" placeholder="Naam" /></div>
<div class="field"><input type="email" placeholder="E-mail" /></div>
<button type="submit" class="kinetic-btn">STUUR NU →</button>
</form>
<div class="kinetic-overlay">
<canvas class="shader-canvas"></canvas>
<p class="kinetic-msg">VERZONDEN</p>
</div>
</div> /* Styling: form-shader-success-kinetic */
:root {
--block-bg: #0A0A0A;
--block-ink: #F4F1EB;
--block-hot: #FF4A1C;
--block-rule: rgba(244,241,235,.15);
}
.kinetic-wrap { position: relative; background: var(--block-bg); color: var(--block-ink); font-family: 'Archivo', sans-serif; padding: clamp(3rem,6vw,5rem) clamp(1.5rem,4vw,4rem); min-height: 70vh; display: flex; flex-direction: column; }
.kinetic-form { max-width: 480px; display: flex; flex-direction: column; gap: 1.5rem; }
.field input { width: 100%; background: transparent; border: 0; border-bottom: 1px solid var(--block-rule); padding: .7rem 0; font: 400 1rem 'Archivo',sans-serif; color: var(--block-ink); outline: none; }
.field input::placeholder { color: rgba(244,241,235,.35); }
.kinetic-btn { align-self: flex-start; background: var(--block-hot); color: #0A0A0A; border: 0; padding: 1rem 2.5rem; font: 700 .9rem 'Archivo',sans-serif; letter-spacing: .12em; cursor: pointer; }
.kinetic-overlay { position: absolute; inset: 0; opacity: 0; visibility: hidden; transition: opacity .4s ease; display: flex; align-items: center; justify-content: center; pointer-events: none; }
.kinetic-overlay.on { opacity: 1; visibility: visible; pointer-events: auto; }
.shader-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.kinetic-msg { position: relative; font-family: 'Archivo', sans-serif; font-weight: 700; font-size: clamp(2rem,6vw,4rem); letter-spacing: -.03em; color: #F4F1EB; text-transform: uppercase; }