SharpMeow commited on
Commit
429dca7
·
verified ·
1 Parent(s): 2c9741e

Hero: rows of lasagna slices in a field

Browse files
Files changed (1) hide show
  1. index.html +35 -17
index.html CHANGED
@@ -298,24 +298,42 @@ let cur=0,view='xy',tab='get';
298
  const n=dark?'light':'dark';document.documentElement.dataset.theme=n;try{localStorage.setItem('lf-theme',n)}catch(e){}};})();
299
 
300
  /* hero: fields of lasagna */
301
- (function(){const W=1600,H=900,svg=$('fields');let seed=7;const rnd=()=>(seed=(seed*16807)%2147483647)/2147483647;
302
  const dark=()=>document.documentElement.dataset.theme?document.documentElement.dataset.theme==='dark':matchMedia('(prefers-color-scheme: dark)').matches;
303
- function draw(){const d=dark();seed=7;
304
- let h='<defs><linearGradient id="sky" x1="0" y1="0" x2="0" y2="1">'+(d?'<stop offset="0" stop-color="#141210"/><stop offset=".6" stop-color="#3a1f17"/><stop offset="1" stop-color="#6b3020"/>':'<stop offset="0" stop-color="#f7f2ea"/><stop offset=".55" stop-color="#fbe3c4"/><stop offset="1" stop-color="#f6b98a"/>')+'</linearGradient>'+
305
- '<radialGradient id="sun"><stop offset="0" stop-color="'+(d?'#ffd9a0':'#fff4d6')+'"/><stop offset="1" stop-color="'+(d?'#ffd9a0':'#ffe2a8')+'" stop-opacity="0"/></radialGradient></defs>';
306
- h+='<rect width="'+W+'" height="'+H+'" fill="url(#sky)"/><circle cx="1240" cy="330" r="190" fill="url(#sun)" opacity="'+(d?.55:.9)+'"/>';
307
- const pasta=d?['#d9b45c','#c99f48']:['#f2cf78','#e6bb5e'],sauce=d?'#a8321c':'#c2462b',cheese=d?'#e9d9b0':'#fff3d1',basil=d?'#5f8f45':'#4f7a3a';
308
- const bands=7;
309
- for(let b=0;b<bands;b++){const t=b/(bands-1),base=430+t*t*430,A=10+t*38,f=.0026+rnd()*.0016,ph=rnd()*6.3,th=2.5+t*11,L=7;
310
- const top=x=>base+Math.sin(x*f+ph)*A+Math.sin(x*f*2.7+ph*1.7)*A*.35;
311
- for(let k=0;k<=L;k++){const pastaLayer=k%2===0,col=k===L?(d?'#b98a3e':'#e2ac58'):k===0?pasta[0]:(pastaLayer?pasta[1]:(k%4===1?sauce:cheese));
312
- let path='M -10 '+H;for(let x=-10;x<=W+10;x+=12){let y=top(x)+k*th;if(pastaLayer)y+=Math.sin(x*.09+k)*th*.18;path+=' L '+x+' '+y.toFixed(1)}
313
- path+=' L '+(W+10)+' '+H+' Z';h+='<path d="'+path+'" fill="'+col+'"/>'}
314
- let ridge='M -10 '+top(-10).toFixed(1);for(let x=-10;x<=W+10;x+=12)ridge+=' L '+x+' '+(top(x)+Math.sin(x*.09)*th*.18).toFixed(1);
315
- h+='<path d="'+ridge+'" fill="none" stroke="'+(d?'#f0d48a':'#fff0c2')+'" stroke-width="'+(1+t*2)+'" opacity=".7"/>';
316
- const n=Math.round(6+t*14);for(let i=0;i<n;i++){const x=rnd()*W,y=top(x)-1,s=2.5+t*7,r=rnd()*60-30;
317
- h+='<ellipse cx="'+x.toFixed(0)+'" cy="'+y.toFixed(1)+'" rx="'+(s*1.6).toFixed(1)+'" ry="'+s.toFixed(1)+'" fill="'+basil+'" transform="rotate('+r.toFixed(0)+' '+x.toFixed(0)+' '+y.toFixed(1)+')"/>';
318
- if(rnd()<.35)h+='<circle cx="'+(x+s*2).toFixed(0)+'" cy="'+(y+s*.4).toFixed(1)+'" r="'+(s*.8).toFixed(1)+'" fill="'+cheese+'"/>'}}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
319
  svg.innerHTML=h}
320
  draw();matchMedia('(prefers-color-scheme: dark)').addEventListener('change',draw);$('theme').addEventListener('click',()=>setTimeout(draw,0));})();
321
 
 
298
  const n=dark?'light':'dark';document.documentElement.dataset.theme=n;try{localStorage.setItem('lf-theme',n)}catch(e){}};})();
299
 
300
  /* hero: fields of lasagna */
301
+ (function(){const W=1600,H=900,svg=$('fields');let seed=11;const rnd=()=>(seed=(seed*16807)%2147483647)/2147483647;
302
  const dark=()=>document.documentElement.dataset.theme?document.documentElement.dataset.theme==='dark':matchMedia('(prefers-color-scheme: dark)').matches;
303
+ const f1=v=>v.toFixed(1);
304
+ function slice(x,y,s,d){/* front face top-left at x,y; s = scale */
305
+ const w=64*s,dp=30*s,h=36*s,ox=dp*.62,oy=-dp*.5,o=[];
306
+ const pasta=d?'#e0b860':'#f4cf73',pastaD=d?'#b88f3f':'#d9aa4f',sauce=d?'#9e2b17':'#b8351d',sauceD=d?'#7d200f':'#922814',ric=d?'#efe2c0':'#fff6dc',ricD=d?'#cdbf9c':'#eadcb6';
307
+ const layers=[[pasta,pastaD,.12],[sauce,sauceD,.16],[ric,ricD,.12],[pasta,pastaD,.12],[sauce,sauceD,.16],[ric,ricD,.12],[pasta,pastaD,.20]];
308
+ o.push('<ellipse cx="'+f1(x+w*.55+ox*.5)+'" cy="'+f1(y+h+2*s)+'" rx="'+f1(w*.62)+'" ry="'+f1(7*s)+'" fill="#000" opacity=".18"/>');
309
+ let yy=y;layers.forEach(([c,cd,fr],i)=>{const t=h*fr,wav=i%3===0?2.2*s:0;
310
+ /* side face band */
311
+ o.push('<path d="M'+f1(x+w)+' '+f1(yy)+' L'+f1(x+w+ox)+' '+f1(yy+oy)+' L'+f1(x+w+ox)+' '+f1(yy+oy+t)+' L'+f1(x+w)+' '+f1(yy+t)+'Z" fill="'+cd+'"/>');
312
+ /* front face band, pasta layers get a ruffled lower edge */
313
+ let pth='M'+f1(x)+' '+f1(yy)+' L'+f1(x+w)+' '+f1(yy)+' L'+f1(x+w)+' '+f1(yy+t);
314
+ if(wav){for(let k=12;k>=0;k--){const xx=x+w*k/12;pth+=' L'+f1(xx)+' '+f1(yy+t+(k%2?wav:-wav*.2))}}else pth+=' L'+f1(x)+' '+f1(yy+t);
315
+ o.push('<path d="'+pth+'Z" fill="'+c+'"/>');yy+=t});
316
+ /* ruffled pasta ends sticking out on the left */
317
+ [0,3,6].forEach(i=>{const ty=y+h*[0,.52,.82][[0,3,6].indexOf(i)];let q='M'+f1(x)+' '+f1(ty);for(let k=0;k<=4;k++)q+=' L'+f1(x-(k%2?4.5:2)*s)+' '+f1(ty+k*1.4*s);q+=' L'+f1(x)+' '+f1(ty+6*s)+'Z';o.push('<path d="'+q+'" fill="'+(d?'#e0b860':'#f4cf73')+'"/>')});
318
+ /* top: melted cheese with browned spots, sauce and basil */
319
+ const top='M'+f1(x)+' '+f1(y)+' L'+f1(x+w)+' '+f1(y)+' L'+f1(x+w+ox)+' '+f1(y+oy)+' L'+f1(x+ox)+' '+f1(y+oy)+'Z';
320
+ o.push('<path d="'+top+'" fill="'+(d?'#e7c66f':'#f7d77e')+'"/>');
321
+ for(let i=0;i<4;i++){const u=rnd(),v=rnd();o.push('<ellipse cx="'+f1(x+u*w*.85+v*ox+4*s)+'" cy="'+f1(y+v*oy+1)+'" rx="'+f1((3+rnd()*4)*s)+'" ry="'+f1((1.4+rnd()*1.6)*s)+'" fill="'+(rnd()<.5?(d?'#a8321c':'#c2462b'):(d?'#9a6a2a':'#c98a3a'))+'" opacity=".9"/>')}
322
+ /* cheese drips over the front edge */
323
+ for(let i=0;i<3;i++){const dx=x+(.15+rnd()*.7)*w,dl=(3+rnd()*5)*s;o.push('<path d="M'+f1(dx-2.5*s)+' '+f1(y)+' Q'+f1(dx-2.5*s)+' '+f1(y+dl)+' '+f1(dx)+' '+f1(y+dl)+' Q'+f1(dx+2.5*s)+' '+f1(y+dl)+' '+f1(dx+2.5*s)+' '+f1(y)+'Z" fill="'+(d?'#e7c66f':'#f7d77e')+'"/>')}
324
+ const bx=x+w*.55+ox*.5,by=y+oy*.5;o.push('<ellipse cx="'+f1(bx)+'" cy="'+f1(by)+'" rx="'+f1(6*s)+'" ry="'+f1(2.6*s)+'" fill="'+(d?'#5f8f45':'#3f7a2e')+'" transform="rotate(-18 '+f1(bx)+' '+f1(by)+')"/><ellipse cx="'+f1(bx+5*s)+'" cy="'+f1(by-1.5*s)+'" rx="'+f1(4.5*s)+'" ry="'+f1(2*s)+'" fill="'+(d?'#6fa252':'#4f8f3a')+'" transform="rotate(24 '+f1(bx+5*s)+' '+f1(by-1.5*s)+')"/>');
325
+ return o.join('')}
326
+ function draw(){const d=dark();seed=11;
327
+ let h='<defs><linearGradient id="sky" x1="0" y1="0" x2="0" y2="1">'+(d?'<stop offset="0" stop-color="#141210"/><stop offset=".55" stop-color="#2c1d18"/><stop offset="1" stop-color="#4a2a1c"/>':'<stop offset="0" stop-color="#f7f2ea"/><stop offset=".5" stop-color="#fbe8cf"/><stop offset="1" stop-color="#f9d3a8"/>')+'</linearGradient>'+
328
+ '<linearGradient id="grass" x1="0" y1="0" x2="0" y2="1">'+(d?'<stop offset="0" stop-color="#2f3b22"/><stop offset="1" stop-color="#1d2616"/>':'<stop offset="0" stop-color="#b9cf86"/><stop offset="1" stop-color="#7fa557"/>')+'</linearGradient>'+
329
+ '<radialGradient id="sun"><stop offset="0" stop-color="'+(d?'#ffd9a0':'#fff6dc')+'"/><stop offset="1" stop-color="#ffe2a8" stop-opacity="0"/></radialGradient></defs>';
330
+ const hz=420;
331
+ h+='<rect width="'+W+'" height="'+H+'" fill="url(#sky)"/><circle cx="1260" cy="300" r="170" fill="url(#sun)" opacity="'+(d?.5:.95)+'"/>';
332
+ h+='<path d="M0 '+hz+' Q400 '+(hz-25)+' 800 '+(hz-5)+' T1600 '+(hz-15)+' L1600 900 L0 900Z" fill="url(#grass)"/>';
333
+ /* furrows converge to a vanishing point */
334
+ for(let i=-12;i<=24;i++){const xb=800+i*120;h+='<line x1="'+(800+i*14)+'" y1="'+hz+'" x2="'+xb+'" y2="900" stroke="'+(d?'#3b4a2b':'#a3bd72')+'" stroke-width="2" opacity=".6"/>'}
335
+ const rows=[[440,.30,22],[470,.42,17],[512,.58,13],[570,.80,10],[650,1.08,8],[760,1.45,6],[890,1.9,5]];
336
+ rows.forEach(([y,sc,n],r)=>{const span=W*1.15,step=span/n;for(let i=0;i<n;i++){const x=-W*.05+i*step+(r%2?step*.5:0)+(rnd()-.5)*step*.15;h+=slice(x,y-36*sc,sc,d)}});
337
  svg.innerHTML=h}
338
  draw();matchMedia('(prefers-color-scheme: dark)').addEventListener('change',draw);$('theme').addEventListener('click',()=>setTimeout(draw,0));})();
339