Liveloop

An interactive timeline for social media. Every post is a tiny app you can play, save, and remix.

Product

  • Feed
  • Create
  • Claude Code plugin
  • Blog

Legal

  • Privacy Policy
  • Terms of Service
  • Cookie Policy
  • DMCA

Project

  • Templates
© 2026 Liveloop. All rights reserved.
LiveloopVersion history

v1Current

@mae_arcade · 6/9/2026, 10:51:31 PM

Initial version — all lines are new.

+<style>
+ html,body{height:100%;margin:0;overflow:hidden;background:#FFF3E4;}
+ *{box-sizing:border-box;}
+ #wrap{position:relative;height:100%;width:100%;display:flex;flex-direction:column;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;background:radial-gradient(110% 80% at 50% 0%,#FFF9EF 0%,#FFEFD8 70%,#FFE3C2 100%);-webkit-tap-highlight-color:transparent;touch-action:manipulation;user-select:none;-webkit-user-select:none;}
+ #head{padding:1.15rem 1.25rem .4rem;}
+ #head h1{margin:0;font-family:"Instrument Serif",Georgia,"Times New Roman",serif;font-weight:400;font-size:2.35rem;line-height:1;color:#4a3a55;}
+ #head p{margin:.2rem 0 0;font-size:.8rem;color:#a08d77;font-weight:500;}
+ #stage{flex:1;display:flex;align-items:center;justify-content:center;min-height:0;padding:.4rem 1.1rem;}
+ #pickWrap{text-align:center;}
+ #pick{border:0;border-radius:999px;background:linear-gradient(135deg,#7C5CFF,#FF5A1F);color:#fff;font-weight:700;font-size:1rem;padding:.95rem 1.7rem;cursor:pointer;box-shadow:0 10px 26px rgba(124,92,255,.35);}
+ #pick:active{transform:scale(.96);}
+ #pickNote{margin-top:.7rem;font-size:.72rem;color:#a08d77;font-weight:600;}
+ #shot{position:relative;max-height:100%;max-width:100%;display:none;}
+ #cv{display:block;max-height:62vh;max-width:100%;border-radius:14px;box-shadow:0 14px 34px rgba(90,60,30,.25);background:#fff;}
+ #result{display:none;max-height:62vh;max-width:100%;border-radius:14px;box-shadow:0 14px 34px rgba(90,60,30,.25);}
+ #file{display:none;}
+ #filters{display:none;gap:8px;overflow-x:auto;padding:.5rem 1.1rem .2rem;scrollbar-width:none;}
+ #filters::-webkit-scrollbar{display:none;}
+ .chip{flex-shrink:0;border:1px solid rgba(120,90,50,.22);background:rgba(255,255,255,.6);color:#6a5440;border-radius:999px;font-size:.74rem;font-weight:700;padding:.45rem .9rem;cursor:pointer;}
+ .chip.on{background:#4a3a55;color:#FFF3E4;border-color:#4a3a55;}
+ #capRow{display:none;padding:.45rem 1.1rem 0;}
+ #cap{width:100%;border:1px solid rgba(120,90,50,.25);background:rgba(255,255,255,.75);border-radius:12px;padding:.6rem .8rem;font-size:16px;color:#4a3a55;font-family:inherit;outline:none;}
+ #foot{display:flex;gap:10px;justify-content:center;padding:.7rem 1.1rem 1.15rem;}
+ #foot button{display:none;border:0;border-radius:999px;font-weight:700;font-size:.85rem;padding:.7rem 1.25rem;cursor:pointer;}
+ #done{background:#4a3a55;color:#FFF3E4;}
+ #again{background:rgba(255,255,255,.7);color:#6a5440;border:1px solid rgba(120,90,50,.25)!important;}
+ #saveHint{display:none;text-align:center;font-size:.72rem;color:#a08d77;font-weight:600;padding-bottom:.4rem;}
+</style>
+<div id="wrap">
+ <div id="head"><h1>Photo Booth</h1><p>One photo, six warm films. Stays on your device.</p></div>
+ <div id="stage">
+ <div id="pickWrap">
+ <button id="pick">&#128247; add a photo</button>
+ <div id="pickNote">your photo never leaves this phone</div>
+ </div>
+ <div id="shot"><canvas id="cv"></canvas></div>
+ <img id="result" alt="your photo">
+ </div>
+ <div id="filters"></div>
+ <div id="capRow"><input id="cap" maxlength="48" placeholder="write a caption (optional)"></div>
+ <div id="saveHint">press &amp; hold the photo to save it</div>
+ <div id="foot">
+ <button id="again">new photo</button>
+ <button id="done">develop &#10024;</button>
+ </div>
+ <input id="file" type="file" accept="image/*">
+</div>
+<script>
+(function(){
+ var LL=window.liveloop||null;
+ var muted = LL ? LL.muted : true;
+ if(LL && LL.onMute){ try{ LL.onMute(function(m){ muted=m; }); }catch(e){} }
+ if(LL && LL.declareMedia){ try{ LL.declareMedia({sound:true}); }catch(e){} }
+ var _ac=null;
+ function actx(){ if(!_ac){ try{ _ac=new (window.AudioContext||window.webkitAudioContext)(); }catch(e){ _ac=null; } } return _ac; }
+ function shutter(){
+ if(muted) return; var c=actx(); if(!c) return;
+ var t=c.currentTime;
+ var n=Math.floor(c.sampleRate*0.05), b=c.createBuffer(1,n,c.sampleRate), d=b.getChannelData(0);
+ for(var i=0;i<n;i++){ d[i]=(Math.random()*2-1)*Math.pow(1-i/n,2); }
+ var s=c.createBufferSource(); s.buffer=b;
+ var g=c.createGain(); g.gain.value=0.15; s.connect(g); g.connect(c.destination); s.start(t);
+ var o=c.createOscillator(), g2=c.createGain();
+ o.type='square'; o.frequency.setValueAtTime(1800,t);
+ g2.gain.setValueAtTime(0.0001,t); g2.gain.exponentialRampToValueAtTime(0.06,t+0.005);
+ g2.gain.exponentialRampToValueAtTime(0.0001,t+0.07);
+ o.connect(g2); g2.connect(c.destination); o.start(t); o.stop(t+0.08);
+ }
+
+ var pickWrap=document.getElementById('pickWrap');
+ var pickBtn=document.getElementById('pick');
+ var fileIn=document.getElementById('file');
+ var shot=document.getElementById('shot');
+ var cv=document.getElementById('cv'), ctx=cv.getContext('2d');
+ var result=document.getElementById('result');
+ var filtersEl=document.getElementById('filters');
+ var capRow=document.getElementById('capRow'), capIn=document.getElementById('cap');
+ var doneBtn=document.getElementById('done'), againBtn=document.getElementById('again');
+ var saveHint=document.getElementById('saveHint');
+
+ var img=null; // downscaled source image (canvas)
+ var current='golden';
+
+ // --- pixel filters (no ctx.filter — works everywhere incl. older iOS)
+ function clamp(v){ return v<0?0:(v>255?255:v); }
+ function applyPixels(data,kind){
+ var d=data.data, i, r,g,b, n=d.length;
+ for(i=0;i<n;i+=4){
+ r=d[i]; g=d[i+1]; b=d[i+2];
+ if(kind==='golden'){
+ r=r*1.12+10; g=g*1.05+2; b=b*0.86;
+ r=(r-128)*1.06+128; g=(g-128)*1.06+128; b=(b-128)*1.06+128;
+ } else if(kind==='film'){
+ var avg=(r+g+b)/3;
+ r=r*0.7+avg*0.3+8; g=g*0.7+avg*0.3+6; b=b*0.7+avg*0.3+10;
+ r=r*0.92+18; g=g*0.92+16; b=b*0.92+20; // lifted blacks
+ } else if(kind==='noir'){
+ var y=r*0.299+g*0.587+b*0.114;
+ y=(y-128)*1.25+128;
+ r=g=b=y;
+ } else if(kind==='vapor'){
+ var lum=(r+g+b)/3;
+ r=r*0.75+lum*0.2+45; b=b*0.75+lum*0.2+60; g=g*0.82+lum*0.1;
+ } else if(kind==='cozy'){
+ var tr=r*0.393+g*0.769+b*0.189, tg=r*0.349+g*0.686+b*0.168, tb=r*0.272+g*0.534+b*0.131;
+ r=r*0.45+tr*0.55; g=g*0.45+tg*0.55; b=b*0.45+tb*0.55;
+ }
+ d[i]=clamp(r); d[i+1]=clamp(g); d[i+2]=clamp(b);
+ }
+ }
+ function grain(c2,w,h,amt){
+ var t=document.createElement('canvas'); t.width=128; t.height=128;
+ var tc=t.getContext('2d'), id=tc.createImageData(128,128), d=id.data;
+ for(var i=0;i<d.length;i+=4){ var v=Math.random()*255; d[i]=d[i+1]=d[i+2]=v; d[i+3]=255; }
+ tc.putImageData(id,0,0);
+ c2.globalAlpha=amt; c2.globalCompositeOperation='overlay';
+ for(var y=0;y<h;y+=128){ for(var x=0;x<w;x+=128){ c2.drawImage(t,x,y); } }
+ c2.globalAlpha=1; c2.globalCompositeOperation='source-over';
+ }
+ function vignette(c2,w,h,amt){
+ var g=c2.createRadialGradient(w/2,h/2,Math.min(w,h)*0.35,w/2,h/2,Math.max(w,h)*0.75);
+ g.addColorStop(0,'rgba(0,0,0,0)'); g.addColorStop(1,'rgba(25,12,0,'+amt+')');
+ c2.fillStyle=g; c2.fillRect(0,0,w,h);
+ }
+
+ var FILTERS=[
+ {k:'original',n:'original'},{k:'golden',n:'golden'},{k:'film',n:'film'},
+ {k:'cozy',n:'cozy'},{k:'noir',n:'noir'},{k:'vapor',n:'vapor'}
+ ];
+ FILTERS.forEach(function(f){
+ var b=document.createElement('button'); b.className='chip'+(f.k===current?' on':''); b.textContent=f.n;
+ b.addEventListener('click',function(){
+ current=f.k;
+ [].forEach.call(filtersEl.children,function(ch){ ch.classList.remove('on'); });
+ b.classList.add('on'); render(); shutter();
+ });
+ filtersEl.appendChild(b);
+ });
+
+ function render(){
+ if(!img) return;
+ var w=img.width, h=img.height;
+ cv.width=w; cv.height=h;
+ ctx.drawImage(img,0,0);
+ if(current!=='original'){
+ var id=ctx.getImageData(0,0,w,h);
+ applyPixels(id,current);
+ ctx.putImageData(id,0,0);
+ }
+ if(current==='film'||current==='noir') grain(ctx,w,h,0.10);
+ if(current!=='original') vignette(ctx,w,h,current==='noir'?0.4:0.24);
+ }
+
+ function load(file){
+ var rd=new FileReader();
+ rd.onload=function(){
+ var im=new Image();
+ im.onload=function(){
+ var MAX=1080, sc=Math.min(1,MAX/Math.max(im.width,im.height));
+ var c2=document.createElement('canvas');
+ c2.width=Math.round(im.width*sc); c2.height=Math.round(im.height*sc);
+ c2.getContext('2d').drawImage(im,0,0,c2.width,c2.height);
+ img=c2;
+ pickWrap.style.display='none'; result.style.display='none';
+ shot.style.display='block'; filtersEl.style.display='flex';
+ capRow.style.display='block'; doneBtn.style.display='block'; againBtn.style.display='block';
+ saveHint.style.display='none';
+ render(); shutter();
+ };
+ im.src=rd.result;
+ };
+ rd.readAsDataURL(file);
+ }
+ pickBtn.addEventListener('click',function(){ fileIn.click(); });
+ fileIn.addEventListener('change',function(){ if(fileIn.files && fileIn.files[0]) load(fileIn.files[0]); });
+
+ doneBtn.addEventListener('click',function(){
+ if(!img) return;
+ // compose the matte: white border + caption strip
+ var w=img.width, h=img.height, M=Math.round(w*0.045), CAP=Math.round(w*0.16);
+ var out=document.createElement('canvas');
+ out.width=w+M*2; out.height=h+M*2+CAP;
+ var oc=out.getContext('2d');
+ oc.fillStyle='#FFFDF7'; oc.fillRect(0,0,out.width,out.height);
+ oc.drawImage(cv,M,M);
+ var cap=(capIn.value||'').trim();
+ oc.fillStyle='#4a3a55'; oc.textAlign='center';
+ oc.font='italic '+Math.round(CAP*0.34)+'px Georgia,"Times New Roman",serif';
+ if(cap) oc.fillText(cap,out.width/2,h+M+CAP*0.52,w);
+ oc.fillStyle='#b9a88c';
+ oc.font=Math.round(CAP*0.18)+'px Georgia,serif';
+ var d=new Date();
+ oc.fillText(d.toLocaleDateString(undefined,{month:'short',day:'numeric',year:'numeric'}),out.width/2,h+M+CAP*0.84);
+ result.src=out.toDataURL('image/jpeg',0.92);
+ shot.style.display='none'; filtersEl.style.display='none'; capRow.style.display='none';
+ doneBtn.style.display='none';
+ result.style.display='block'; saveHint.style.display='block';
+ shutter();
+ });
+ againBtn.addEventListener('click',function(){
+ img=null; fileIn.value='';
+ shot.style.display='none'; result.style.display='none';
+ filtersEl.style.display='none'; capRow.style.display='none';
+ doneBtn.style.display='none'; againBtn.style.display='none'; saveHint.style.display='none';
+ pickWrap.style.display='block'; capIn.value='';
+ });
+})();
+</script>

v1Current

@mae_arcade · 6/9/2026, 10:51:31 PM

Initial version — all lines are new.

+<style>
+ html,body{height:100%;margin:0;overflow:hidden;background:#FFF3E4;}
+ *{box-sizing:border-box;}
+ #wrap{position:relative;height:100%;width:100%;display:flex;flex-direction:column;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;background:radial-gradient(110% 80% at 50% 0%,#FFF9EF 0%,#FFEFD8 70%,#FFE3C2 100%);-webkit-tap-highlight-color:transparent;touch-action:manipulation;user-select:none;-webkit-user-select:none;}
+ #head{padding:1.15rem 1.25rem .4rem;}
+ #head h1{margin:0;font-family:"Instrument Serif",Georgia,"Times New Roman",serif;font-weight:400;font-size:2.35rem;line-height:1;color:#4a3a55;}
+ #head p{margin:.2rem 0 0;font-size:.8rem;color:#a08d77;font-weight:500;}
+ #stage{flex:1;display:flex;align-items:center;justify-content:center;min-height:0;padding:.4rem 1.1rem;}
+ #pickWrap{text-align:center;}
+ #pick{border:0;border-radius:999px;background:linear-gradient(135deg,#7C5CFF,#FF5A1F);color:#fff;font-weight:700;font-size:1rem;padding:.95rem 1.7rem;cursor:pointer;box-shadow:0 10px 26px rgba(124,92,255,.35);}
+ #pick:active{transform:scale(.96);}
+ #pickNote{margin-top:.7rem;font-size:.72rem;color:#a08d77;font-weight:600;}
+ #shot{position:relative;max-height:100%;max-width:100%;display:none;}
+ #cv{display:block;max-height:62vh;max-width:100%;border-radius:14px;box-shadow:0 14px 34px rgba(90,60,30,.25);background:#fff;}
+ #result{display:none;max-height:62vh;max-width:100%;border-radius:14px;box-shadow:0 14px 34px rgba(90,60,30,.25);}
+ #file{display:none;}
+ #filters{display:none;gap:8px;overflow-x:auto;padding:.5rem 1.1rem .2rem;scrollbar-width:none;}
+ #filters::-webkit-scrollbar{display:none;}
+ .chip{flex-shrink:0;border:1px solid rgba(120,90,50,.22);background:rgba(255,255,255,.6);color:#6a5440;border-radius:999px;font-size:.74rem;font-weight:700;padding:.45rem .9rem;cursor:pointer;}
+ .chip.on{background:#4a3a55;color:#FFF3E4;border-color:#4a3a55;}
+ #capRow{display:none;padding:.45rem 1.1rem 0;}
+ #cap{width:100%;border:1px solid rgba(120,90,50,.25);background:rgba(255,255,255,.75);border-radius:12px;padding:.6rem .8rem;font-size:16px;color:#4a3a55;font-family:inherit;outline:none;}
+ #foot{display:flex;gap:10px;justify-content:center;padding:.7rem 1.1rem 1.15rem;}
+ #foot button{display:none;border:0;border-radius:999px;font-weight:700;font-size:.85rem;padding:.7rem 1.25rem;cursor:pointer;}
+ #done{background:#4a3a55;color:#FFF3E4;}
+ #again{background:rgba(255,255,255,.7);color:#6a5440;border:1px solid rgba(120,90,50,.25)!important;}
+ #saveHint{display:none;text-align:center;font-size:.72rem;color:#a08d77;font-weight:600;padding-bottom:.4rem;}
+</style>
+<div id="wrap">
+ <div id="head"><h1>Photo Booth</h1><p>One photo, six warm films. Stays on your device.</p></div>
+ <div id="stage">
+ <div id="pickWrap">
+ <button id="pick">&#128247; add a photo</button>
+ <div id="pickNote">your photo never leaves this phone</div>
+ </div>
+ <div id="shot"><canvas id="cv"></canvas></div>
+ <img id="result" alt="your photo">
+ </div>
+ <div id="filters"></div>
+ <div id="capRow"><input id="cap" maxlength="48" placeholder="write a caption (optional)"></div>
+ <div id="saveHint">press &amp; hold the photo to save it</div>
+ <div id="foot">
+ <button id="again">new photo</button>
+ <button id="done">develop &#10024;</button>
+ </div>
+ <input id="file" type="file" accept="image/*">
+</div>
+<script>
+(function(){
+ var LL=window.liveloop||null;
+ var muted = LL ? LL.muted : true;
+ if(LL && LL.onMute){ try{ LL.onMute(function(m){ muted=m; }); }catch(e){} }
+ if(LL && LL.declareMedia){ try{ LL.declareMedia({sound:true}); }catch(e){} }
+ var _ac=null;
+ function actx(){ if(!_ac){ try{ _ac=new (window.AudioContext||window.webkitAudioContext)(); }catch(e){ _ac=null; } } return _ac; }
+ function shutter(){
+ if(muted) return; var c=actx(); if(!c) return;
+ var t=c.currentTime;
+ var n=Math.floor(c.sampleRate*0.05), b=c.createBuffer(1,n,c.sampleRate), d=b.getChannelData(0);
+ for(var i=0;i<n;i++){ d[i]=(Math.random()*2-1)*Math.pow(1-i/n,2); }
+ var s=c.createBufferSource(); s.buffer=b;
+ var g=c.createGain(); g.gain.value=0.15; s.connect(g); g.connect(c.destination); s.start(t);
+ var o=c.createOscillator(), g2=c.createGain();
+ o.type='square'; o.frequency.setValueAtTime(1800,t);
+ g2.gain.setValueAtTime(0.0001,t); g2.gain.exponentialRampToValueAtTime(0.06,t+0.005);
+ g2.gain.exponentialRampToValueAtTime(0.0001,t+0.07);
+ o.connect(g2); g2.connect(c.destination); o.start(t); o.stop(t+0.08);
+ }
+
+ var pickWrap=document.getElementById('pickWrap');
+ var pickBtn=document.getElementById('pick');
+ var fileIn=document.getElementById('file');
+ var shot=document.getElementById('shot');
+ var cv=document.getElementById('cv'), ctx=cv.getContext('2d');
+ var result=document.getElementById('result');
+ var filtersEl=document.getElementById('filters');
+ var capRow=document.getElementById('capRow'), capIn=document.getElementById('cap');
+ var doneBtn=document.getElementById('done'), againBtn=document.getElementById('again');
+ var saveHint=document.getElementById('saveHint');
+
+ var img=null; // downscaled source image (canvas)
+ var current='golden';
+
+ // --- pixel filters (no ctx.filter — works everywhere incl. older iOS)
+ function clamp(v){ return v<0?0:(v>255?255:v); }
+ function applyPixels(data,kind){
+ var d=data.data, i, r,g,b, n=d.length;
+ for(i=0;i<n;i+=4){
+ r=d[i]; g=d[i+1]; b=d[i+2];
+ if(kind==='golden'){
+ r=r*1.12+10; g=g*1.05+2; b=b*0.86;
+ r=(r-128)*1.06+128; g=(g-128)*1.06+128; b=(b-128)*1.06+128;
+ } else if(kind==='film'){
+ var avg=(r+g+b)/3;
+ r=r*0.7+avg*0.3+8; g=g*0.7+avg*0.3+6; b=b*0.7+avg*0.3+10;
+ r=r*0.92+18; g=g*0.92+16; b=b*0.92+20; // lifted blacks
+ } else if(kind==='noir'){
+ var y=r*0.299+g*0.587+b*0.114;
+ y=(y-128)*1.25+128;
+ r=g=b=y;
+ } else if(kind==='vapor'){
+ var lum=(r+g+b)/3;
+ r=r*0.75+lum*0.2+45; b=b*0.75+lum*0.2+60; g=g*0.82+lum*0.1;
+ } else if(kind==='cozy'){
+ var tr=r*0.393+g*0.769+b*0.189, tg=r*0.349+g*0.686+b*0.168, tb=r*0.272+g*0.534+b*0.131;
+ r=r*0.45+tr*0.55; g=g*0.45+tg*0.55; b=b*0.45+tb*0.55;
+ }
+ d[i]=clamp(r); d[i+1]=clamp(g); d[i+2]=clamp(b);
+ }
+ }
+ function grain(c2,w,h,amt){
+ var t=document.createElement('canvas'); t.width=128; t.height=128;
+ var tc=t.getContext('2d'), id=tc.createImageData(128,128), d=id.data;
+ for(var i=0;i<d.length;i+=4){ var v=Math.random()*255; d[i]=d[i+1]=d[i+2]=v; d[i+3]=255; }
+ tc.putImageData(id,0,0);
+ c2.globalAlpha=amt; c2.globalCompositeOperation='overlay';
+ for(var y=0;y<h;y+=128){ for(var x=0;x<w;x+=128){ c2.drawImage(t,x,y); } }
+ c2.globalAlpha=1; c2.globalCompositeOperation='source-over';
+ }
+ function vignette(c2,w,h,amt){
+ var g=c2.createRadialGradient(w/2,h/2,Math.min(w,h)*0.35,w/2,h/2,Math.max(w,h)*0.75);
+ g.addColorStop(0,'rgba(0,0,0,0)'); g.addColorStop(1,'rgba(25,12,0,'+amt+')');
+ c2.fillStyle=g; c2.fillRect(0,0,w,h);
+ }
+
+ var FILTERS=[
+ {k:'original',n:'original'},{k:'golden',n:'golden'},{k:'film',n:'film'},
+ {k:'cozy',n:'cozy'},{k:'noir',n:'noir'},{k:'vapor',n:'vapor'}
+ ];
+ FILTERS.forEach(function(f){
+ var b=document.createElement('button'); b.className='chip'+(f.k===current?' on':''); b.textContent=f.n;
+ b.addEventListener('click',function(){
+ current=f.k;
+ [].forEach.call(filtersEl.children,function(ch){ ch.classList.remove('on'); });
+ b.classList.add('on'); render(); shutter();
+ });
+ filtersEl.appendChild(b);
+ });
+
+ function render(){
+ if(!img) return;
+ var w=img.width, h=img.height;
+ cv.width=w; cv.height=h;
+ ctx.drawImage(img,0,0);
+ if(current!=='original'){
+ var id=ctx.getImageData(0,0,w,h);
+ applyPixels(id,current);
+ ctx.putImageData(id,0,0);
+ }
+ if(current==='film'||current==='noir') grain(ctx,w,h,0.10);
+ if(current!=='original') vignette(ctx,w,h,current==='noir'?0.4:0.24);
+ }
+
+ function load(file){
+ var rd=new FileReader();
+ rd.onload=function(){
+ var im=new Image();
+ im.onload=function(){
+ var MAX=1080, sc=Math.min(1,MAX/Math.max(im.width,im.height));
+ var c2=document.createElement('canvas');
+ c2.width=Math.round(im.width*sc); c2.height=Math.round(im.height*sc);
+ c2.getContext('2d').drawImage(im,0,0,c2.width,c2.height);
+ img=c2;
+ pickWrap.style.display='none'; result.style.display='none';
+ shot.style.display='block'; filtersEl.style.display='flex';
+ capRow.style.display='block'; doneBtn.style.display='block'; againBtn.style.display='block';
+ saveHint.style.display='none';
+ render(); shutter();
+ };
+ im.src=rd.result;
+ };
+ rd.readAsDataURL(file);
+ }
+ pickBtn.addEventListener('click',function(){ fileIn.click(); });
+ fileIn.addEventListener('change',function(){ if(fileIn.files && fileIn.files[0]) load(fileIn.files[0]); });
+
+ doneBtn.addEventListener('click',function(){
+ if(!img) return;
+ // compose the matte: white border + caption strip
+ var w=img.width, h=img.height, M=Math.round(w*0.045), CAP=Math.round(w*0.16);
+ var out=document.createElement('canvas');
+ out.width=w+M*2; out.height=h+M*2+CAP;
+ var oc=out.getContext('2d');
+ oc.fillStyle='#FFFDF7'; oc.fillRect(0,0,out.width,out.height);
+ oc.drawImage(cv,M,M);
+ var cap=(capIn.value||'').trim();
+ oc.fillStyle='#4a3a55'; oc.textAlign='center';
+ oc.font='italic '+Math.round(CAP*0.34)+'px Georgia,"Times New Roman",serif';
+ if(cap) oc.fillText(cap,out.width/2,h+M+CAP*0.52,w);
+ oc.fillStyle='#b9a88c';
+ oc.font=Math.round(CAP*0.18)+'px Georgia,serif';
+ var d=new Date();
+ oc.fillText(d.toLocaleDateString(undefined,{month:'short',day:'numeric',year:'numeric'}),out.width/2,h+M+CAP*0.84);
+ result.src=out.toDataURL('image/jpeg',0.92);
+ shot.style.display='none'; filtersEl.style.display='none'; capRow.style.display='none';
+ doneBtn.style.display='none';
+ result.style.display='block'; saveHint.style.display='block';
+ shutter();
+ });
+ againBtn.addEventListener('click',function(){
+ img=null; fileIn.value='';
+ shot.style.display='none'; result.style.display='none';
+ filtersEl.style.display='none'; capRow.style.display='none';
+ doneBtn.style.display='none'; againBtn.style.display='none'; saveHint.style.display='none';
+ pickWrap.style.display='block'; capIn.value='';
+ });
+})();
+</script>
← Version history