Creative Visual Effects

Aurora Field Confetti Burst Effect

A confetti burst effect completed for the Aurora Field scenario: includes real content, actionable controls, clear status feedback, and responsive layouts across sizes.

Creative Visual EffectsConfetti Burst EffectHTMLCanvasJavaScript
With JavaScript enabled, you can edit, run, and save this example. The fixed source is as follows:
<!doctype html>
<html lang="en" dir="ltr">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Aurora Field Confetti Burst Effect</title>
  <style>
    :root { --ink:#24213a; --paper:#f6f1e8; --accent:#e6a23c; --secondary:#a8a1d8; --line:color-mix(in srgb, var(--ink) 18%, transparent); --shadow:0 24px 60px color-mix(in srgb, var(--ink) 16%, transparent); color-scheme:light; }
    * { box-sizing:border-box; }
    html { min-width:320px; background:var(--paper); }
    body { min-height:100vh; margin:0; overflow-x:hidden; color:var(--ink); font-family:"Songti SC","Noto Serif SC",Georgia,serif; background:linear-gradient(90deg,transparent 49.7%,color-mix(in srgb,var(--ink) 7%,transparent) 50%,transparent 50.3%),var(--paper); }
    button,input,select,textarea { color:inherit; font:inherit; }
    button,[role="button"],input,select,textarea { accent-color:var(--accent); }
    button { cursor:pointer; }
    button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,[tabindex]:focus-visible { outline:3px solid var(--accent); outline-offset:3px; }
    [hidden] { display:none !important; }
    @media (max-width:700px) { .mast h1 { line-height:1.08 !important; letter-spacing:-.035em !important; overflow-wrap:anywhere; } }
    @media (prefers-reduced-motion:reduce) { *,*::before,*::after { scroll-behavior:auto !important; animation-duration:.01ms !important; animation-iteration-count:1 !important; transition-duration:.01ms !important; } }
    .page{width:min(1180px,calc(100% - 40px));margin:auto;padding:7vw 0}.mast{display:grid;grid-template-columns:minmax(0,1.6fr) minmax(180px,.4fr);gap:5vw;align-items:end;margin-bottom:38px}.mast h1{font-family:"Songti SC",Georgia,serif;font-weight:800;font-size:clamp(42px,9vw,92px);max-width:920px;margin:0;line-height:.94}.eyebrow{display:block;margin-bottom:14px;color:var(--accent);font:800 11px/1 ui-monospace,monospace;letter-spacing:.24em}.intro{max-width:58ch;line-height:1.9}.scenario{align-self:start;padding-top:10px;border-top:1px solid var(--ink);font-style:italic}.demo{border-radius:0;border-width:2px;box-shadow:14px 14px 0 color-mix(in srgb,var(--ink) 18%,transparent);position:relative;overflow:hidden;min-height:420px;padding:clamp(22px,4vw,48px);background:var(--paper)}@media(max-width:700px){.page{width:calc(100% - 22px);padding:26px 0}.mast{grid-template-columns:1fr}.demo{min-height:340px;padding:18px}}
    .panel{padding:16px;border:3px double var(--accent);background:var(--paper)}.stack{display:grid;gap:14px}.row{display:grid;grid-auto-flow:column;grid-auto-columns:max-content;gap:10px;overflow:auto}.action{padding:10px 15px;border:1px solid var(--accent);background:transparent;font-family:Didot,serif;letter-spacing:.06em}.action.primary,.action.is-active{color:var(--paper);background:var(--ink)}.metric{font-family:Didot,serif;font-size:clamp(36px,8vw,74px);letter-spacing:.04em}.status{min-height:24px;padding:9px;border-inline:1px solid var(--accent);text-align:center}.muted{line-height:1.8}.chip{padding:5px 14px;border-inline:1px solid var(--accent);letter-spacing:.1em}.meter{height:5px;background:var(--line)}.meter>i{display:block;height:100%;background:linear-gradient(90deg,var(--accent),var(--secondary))}
    .composition-studio{display:grid;gap:14px}.studio-ruler{display:flex;justify-content:space-between;padding:0 4px;color:color-mix(in srgb,var(--ink) 55%,transparent);font:700 11px/1 ui-monospace,monospace;letter-spacing:.14em}.studio-ruler::before{content:"01 / WORKING PROTOTYPE"}.studio-ruler::after{content:"360 · 768 · 1440"}.composition-studio .demo::after{content:"";position:absolute;right:18px;bottom:18px;width:24px;height:24px;border-right:2px solid var(--accent);border-bottom:2px solid var(--accent);pointer-events:none}
    .confetti-lab{display:grid;grid-template-columns:minmax(0,1.42fr) minmax(220px,.58fr);gap:16px}.confetti-stage{position:relative;min-height:450px;overflow:hidden;border:1px solid var(--line);border-radius:24px;background:linear-gradient(135deg,#172554,#312e81);color:#fff}.confetti-stage canvas{position:absolute;inset:0;width:100%;height:100%;touch-action:none}.confetti-stage>div{position:relative;z-index:2;max-width:600px;padding:clamp(30px,7vw,76px);pointer-events:none}.confetti-stage h2{font-size:clamp(36px,7vw,78px);line-height:.94}.confetti-controls{display:grid;align-content:center;gap:16px}.confetti-controls label{display:grid;grid-template-columns:1fr auto;gap:8px;font-weight:800}.confetti-controls input{grid-column:1/-1}@media(max-width:740px){.confetti-lab{grid-template-columns:1fr}.confetti-stage{min-height:350px}}.workflow-compare{display:grid;grid-template-columns:minmax(230px,.55fr) minmax(0,1.45fr);gap:18px}.compare-stage{display:grid;gap:12px;min-width:0}.compare-stage>header{display:flex;justify-content:space-between;gap:16px;align-items:end}.compare-stage h2{margin:.2em 0}.compare-core{--compare-split:50%;min-width:0;padding:14px;clip-path:inset(0 calc(100% - var(--compare-split)) 0 0);outline:1px dashed var(--accent);outline-offset:-8px;transition:clip-path .25s,filter .25s}.compare-core[data-compare-channel="B"]{filter:hue-rotate(32deg) saturate(1.15)}.compare-controls{display:grid;align-content:start;gap:16px;padding:20px;border:1px solid var(--line);border-radius:24px 4px 24px 4px;background:var(--paper)}.compare-controls fieldset,.compare-controls>label{display:grid;gap:8px}.compare-controls input[type="range"]{width:100%}#workflowCompareShelf{display:grid;gap:6px;padding:0;margin:0;list-style:none}#workflowCompareShelf li{display:grid;grid-template-columns:auto 1fr auto;gap:8px;padding:9px;border-top:1px solid var(--line);font-size:12px}@media(max-width:900px){.workflow-compare{grid-template-columns:1fr}.compare-stage{order:-1}.compare-core{clip-path:none;border-left:8px solid var(--accent)}}
  </style>
</head>
<body data-aesthetic="editorial" data-composition="studio">
  <main class="page">
    <header class="mast"><div><span class="eyebrow">editorial / confetti burst effect / ADVANCED</span><h1>Aurora Field Confetti Burst Effect</h1><p class="intro">A confetti burst effect completed for the Aurora Field scenario: includes real content, actionable controls, clear status feedback, and responsive layouts across sizes.</p></div><span class="scenario">Aurora Field</span></header>
    <div class="composition-studio"><div class="studio-ruler" aria-hidden="true"></div><section class="demo" aria-label="Aurora Field Confetti Burst Interactive Area"><div class="workflow-compare"><form id="workflowCompareControls" class="compare-controls"><fieldset><legend>Reference Channel</legend><label><input type="radio" name="workflowChannel" value="A" checked>A · Green Light Curtain</label><label><input type="radio" name="workflowChannel" value="B">B · magenta light band</label></fieldset><label>Exposure Time Weight<input id="workflowCompareWeight" type="range" min="10" max="90" value="50"><output id="workflowCompareWeightValue">50 seconds</output></label><label><input id="workflowCompareFreeze" type="checkbox">Freeze current version</label><button id="workflowCompareCapture" class="action primary" type="button">Sample and save exposure</button><ol id="workflowCompareShelf" aria-label="Version Sampling Record"></ol></form><section class="compare-stage"><header><span class="eyebrow">Aurora Field COMPARE</span><h2>Aurora A/B Comparison</h2><output id="workflowCompareLive">Version A waiting for sampling</output></header><section id="workflowCore" class="workflow-core compare-core" data-compare-channel="A" style="--compare-split:50%"><!-- 11DZ_CORE_START:creative-effects-confetti-burst --><div class="confetti-lab"><section class="confetti-stage"><canvas id="confettiCanvas" width="960" height="460" aria-label="Aurora Field Confetti Burst Canvas" aria-describedby="confettiHelp">Your browser does not support Canvas.</canvas><div><span>Aurora Field</span><h2>Fill the moments worth celebrating with color</h2><p id="confettiHelp">Click the button or any area on the canvas to trigger confetti.</p></div></section><aside class="confetti-controls panel"><span class="eyebrow">CONFETTI BURST</span><h2>Confetti Burst Effect</h2><label>Burst Count <input id="confettiAmount" type="range" min="20" max="120" value="70" data-core-bridge="creative-effects-confetti-burst"><output id="confettiAmountValue">70</output></label><label>Gravity Strength <input id="confettiGravity" type="range" min="2" max="16" value="8"><output id="confettiGravityValue">8</output></label><button id="confettiBurst" class="action primary" type="button">Release Confetti</button><button id="confettiClear" class="action" type="button">Clear Canvas</button></aside></div><!-- 11DZ_CORE_END --></section></section></div><p id="status" class="status" role="status" aria-live="polite"></p></section></div>
  </main>
  <script>
    'use strict';
    const statusOutput = document.querySelector('#status');
    const announce = message => { statusOutput.textContent = message; };
    /* 11DZ_CORE_SCRIPT_START:creative-effects-confetti-burst */
const confettiCanvas=document.querySelector('#confettiCanvas');const confettiContext=confettiCanvas.getContext('2d');const confettiAmount=document.querySelector('#confettiAmount');const confettiGravity=document.querySelector('#confettiGravity');const confettiReduced=matchMedia('(prefers-reduced-motion: reduce)').matches;let confettiPieces=[];let confettiFrame=0;const confettiColors=['#fde047','#fb7185','#38bdf8','#34d399','#c084fc'];function sizeConfettiCanvas(){const rect=confettiCanvas.getBoundingClientRect();const ratio=Math.min(2,devicePixelRatio||1);confettiCanvas.width=Math.max(320,Math.round(rect.width*ratio));confettiCanvas.height=Math.max(280,Math.round(rect.height*ratio));confettiContext.setTransform(ratio,0,0,ratio,0,0);}function burstConfetti(x,y){const count=Number(confettiAmount.value);for(let index=0;index<count;index+=1){const angle=Math.PI*2*index/count+(index%7)*.08;const speed=2.8+(index%13)*.22;confettiPieces.push({x,y,vx:Math.cos(angle)*speed,vy:Math.sin(angle)*speed-4.8,rotation:index*.7,spin:(index%2?1:-1)*.08,w:5+index%7,h:9+index%8,color:confettiColors[index%confettiColors.length],life:1});}cancelAnimationFrame(confettiFrame);drawConfetti();announce('Released '+count+' Confetti pieces');}function drawConfetti(){const rect=confettiCanvas.getBoundingClientRect();confettiContext.clearRect(0,0,rect.width,rect.height);confettiPieces.forEach(piece=>{if(!confettiReduced){piece.vy+=Number(confettiGravity.value)*.012;piece.x+=piece.vx;piece.y+=piece.vy;piece.rotation+=piece.spin;piece.life-=.004;}confettiContext.save();confettiContext.globalAlpha=Math.max(0,piece.life);confettiContext.translate(piece.x,piece.y);confettiContext.rotate(piece.rotation);confettiContext.fillStyle=piece.color;confettiContext.fillRect(-piece.w/2,-piece.h/2,piece.w,piece.h);confettiContext.restore();});confettiPieces=confettiPieces.filter(piece=>piece.life>0&&piece.y<rect.height+40);if(confettiPieces.length&&!confettiReduced)confettiFrame=requestAnimationFrame(drawConfetti);}document.querySelector('#confettiBurst').addEventListener('click',()=>burstConfetti(confettiCanvas.clientWidth/2,confettiCanvas.clientHeight*.56));confettiCanvas.addEventListener('pointerdown',event=>{const rect=confettiCanvas.getBoundingClientRect();burstConfetti(event.clientX-rect.left,event.clientY-rect.top);});document.querySelector('#confettiClear').addEventListener('click',()=>{confettiPieces=[];cancelAnimationFrame(confettiFrame);drawConfetti();announce('Confetti canvas cleared');});confettiAmount.addEventListener('input',()=>{document.querySelector('#confettiAmountValue').textContent=confettiAmount.value;});confettiGravity.addEventListener('input',()=>{document.querySelector('#confettiGravityValue').textContent=confettiGravity.value;announce('Confetti Gravity '+confettiGravity.value);});addEventListener('resize',sizeConfettiCanvas,{passive:true});sizeConfettiCanvas();
/* 11DZ_CORE_SCRIPT_END */
const workflowBridgeSpec={"name":"creative-effects-confetti-burst","selector":"[data-core-bridge=\"creative-effects-confetti-burst\"]","mode":"range","key":"ArrowRight"};const workflowBridgeCore=document.querySelector('#workflowCore');const workflowBridgeControl=workflowBridgeCore.querySelector(workflowBridgeSpec.selector);if(!workflowBridgeControl)throw new Error('Missing core bridge: '+workflowBridgeSpec.name);const workflowBridgeControlledId=workflowBridgeControl.getAttribute('aria-controls');const workflowBridgeControlled=workflowBridgeControlledId?document.getElementById(workflowBridgeControlledId):null;workflowBridgeCore.dataset.workflowBridge=workflowBridgeSpec.name;workflowBridgeCore.dataset.workflowVersion='0';function workflowBridgeSerialize(){const visualNode=workflowBridgeCore.firstElementChild||workflowBridgeCore;const visual=getComputedStyle(visualNode);const outputs=[...workflowBridgeCore.querySelectorAll('output,[role="status"],[aria-live],meter,progress')].map(node=>node.textContent.trim()+'|'+node.getAttribute('aria-valuenow')+'|'+node.getAttribute('value'));const canvas=[...workflowBridgeCore.querySelectorAll('canvas')].map(node=>{try{return node.toDataURL().slice(-160);}catch{return 'canvas-unavailable';}});return JSON.stringify({html:workflowBridgeCore.innerHTML,status:statusOutput.textContent,outputs,canvas,visual:[visual.display,visual.visibility,visual.opacity,visual.transform,visual.filter,visual.backgroundColor,visual.width,visual.height],scroll:workflowBridgeSpec.mode==='scroll'?workflowBridgeControl.scrollTop:null});}let workflowBridgeLastEffect=workflowBridgeSerialize();function workflowBridgeSummary(){const label=(workflowBridgeControl.getAttribute('aria-label')||workflowBridgeControl.textContent||workflowBridgeControl.value||workflowBridgeSpec.name).trim().replace(/\s+/g,' ').slice(0,72);return label+' · Core Version '+workflowBridgeCore.dataset.workflowVersion;}function workflowBridgeCommit(){const effect=workflowBridgeSerialize();if(effect===workflowBridgeLastEffect)return {changed:false,summary:workflowBridgeSummary()};workflowBridgeLastEffect=effect;workflowBridgeCore.dataset.workflowVersion=String(Number(workflowBridgeCore.dataset.workflowVersion||0)+1);return {changed:true,summary:workflowBridgeSummary()};}function workflowBridgeScheduleCommit(){queueMicrotask(workflowBridgeCommit);setTimeout(workflowBridgeCommit,0);}workflowBridgeControl.addEventListener("input",workflowBridgeScheduleCommit);workflowBridgeControl.addEventListener('change',workflowBridgeScheduleCommit);const workflowBridgeStateTargets=new Set(workflowBridgeCore.querySelectorAll('dialog'));if(workflowBridgeControlled&&workflowBridgeCore.contains(workflowBridgeControlled))workflowBridgeStateTargets.add(workflowBridgeControlled);workflowBridgeStateTargets.forEach(target=>['close','cancel','toggle'].forEach(eventName=>target.addEventListener(eventName,workflowBridgeScheduleCommit)));function workflowBridgeActivate(){workflowBridgeControl.focus();const step=Number(workflowBridgeControl.step)||1;const min=workflowBridgeControl.min===''?-Infinity:Number(workflowBridgeControl.min);const max=workflowBridgeControl.max===''?Infinity:Number(workflowBridgeControl.max);let next=Math.min(max,Math.max(min,(Number(workflowBridgeControl.value)||0)+step));if(next===Number(workflowBridgeControl.value))next=Math.max(min,Number(workflowBridgeControl.value)-step);workflowBridgeControl.value=String(next);workflowBridgeControl.dispatchEvent(new Event('input',{bubbles:true}));workflowBridgeControl.dispatchEvent(new Event('change',{bubbles:true}));const result=workflowBridgeCommit();setTimeout(workflowBridgeCommit,0);return result;}function workflowBridgeReset(){workflowBridgeCore.dataset.workflowVersion='0';workflowBridgeLastEffect=workflowBridgeSerialize();}
const workflowCompareCore=document.querySelector('#workflowCore');const workflowCompareWeight=document.querySelector('#workflowCompareWeight');const workflowCompareState={channel:'A',weight:50,frozen:false,snapshots:[]};function workflowCompareFingerprint(){const controls=[...workflowCompareCore.querySelectorAll('input,select,textarea')];const outputs=[...workflowCompareCore.querySelectorAll('output,[role="status"],strong')].map(node=>node.textContent.trim()).filter(Boolean);return {controlValues:controls.map(control=>control.type==='checkbox'||control.type==='radio'?control.checked:control.value),summary:outputs.slice(0,4).join(' / '),nodes:workflowCompareCore.querySelectorAll('*').length};}function workflowCompareDrive(){workflowCompareCore.dataset.compareChannel=workflowCompareState.channel;workflowCompareCore.style.setProperty('--compare-split',workflowCompareState.weight+'%');document.querySelector('#workflowCompareWeightValue').textContent=workflowCompareState.weight+' sec';document.querySelector('#workflowCompareLive').textContent=workflowCompareState.channel+' Version · '+workflowCompareState.weight+' sec'+(workflowCompareState.frozen?' · Frozen':'');announce('Aurora comparison in progress '+workflowCompareState.channel+' Version');}function workflowCompareCapture(source){const bridge=workflowBridgeActivate();const snapshot={...workflowCompareFingerprint(),channel:workflowCompareState.channel,weight:workflowCompareState.weight,source,bridge:bridge.summary};workflowCompareState.snapshots.push(snapshot);const item=document.createElement('li');item.innerHTML='<b>'+snapshot.channel+'</b><span>'+(snapshot.summary||snapshot.bridge)+'</span><small>'+snapshot.weight+' seconds · '+snapshot.bridge+'</small>';document.querySelector('#workflowCompareShelf').prepend(item);announce('sampled '+snapshot.channel+' Save exposure version · '+bridge.summary);}document.querySelectorAll('[name="workflowChannel"]').forEach(input=>input.addEventListener('change',()=>{workflowCompareState.channel=input.value;workflowCompareDrive();}));workflowCompareWeight.addEventListener('input',()=>{workflowCompareState.weight=Number(workflowCompareWeight.value);workflowCompareDrive();});document.querySelector('#workflowCompareFreeze').addEventListener('change',event=>{workflowCompareState.frozen=event.currentTarget.checked;workflowCompareDrive();});document.querySelector('#workflowCompareCapture').addEventListener('click',()=>workflowCompareCapture('Button Sampling'));workflowCompareCore.addEventListener('dblclick',()=>workflowCompareCapture('Main view double-click'));workflowCompareDrive();
workflowBridgeReset();
  </script>
</body>
</html>
Page feedbackFound an issue or have suggestions for improvement?
Feedback features need to be used in the online version

Please enable JavaScript in the online version before submitting; local features of the current tool or example are not affected.

Go to the online version for feedback