| Server IP : 127.0.0.1 / Your IP : 216.73.216.109 Web Server : Apache/2.4.54 (Win64) OpenSSL/1.1.1q PHP/8.1.10 System : Windows NT DESKTOP-E5T4RUN 10.0 build 19045 (Windows 10) AMD64 User : SERVERWEB ( 0) PHP Version : 8.1.10 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : C:/Users/SERVERWEB/AppData/Local/Microsoft/OneDrive/26.074.0420.0001/WebAssets/static/views/ |
Upload File : |
const canvas=document.getElementById("c"),ctx=canvas.getContext("2d");canvas.width=window.innerWidth,canvas.height=window.innerHeight;const COLS=12,ROWS=8,ITERS=5,GRAVITY=.15,DAMPING=.985;let windLevel=3,gustPower=0,particles=[],constraints=[],cellImages=[],restDist,originX,originY,dragIdx=-1;function buildCloth(){const a=canvas.width,c=canvas.height;restDist=Math.min(a*.55/COLS,c*.6/ROWS,75),originX=a*.18,originY=c*.15,particles=[],constraints=[];for(let e=0;e<=ROWS;e++)for(let o=0;o<=COLS;o++){const t=originX+o*restDist,i=originY+e*restDist;particles.push({x:t,y:i,ox:t,oy:i,pinned:o===0,dragging:!1})}const n=COLS+1;for(let e=0;e<=ROWS;e++)for(let o=0;o<=COLS;o++){const t=e*n+o;o<COLS&&constraints.push({a:t,b:t+1,rest:restDist}),e<ROWS&&constraints.push({a:t,b:t+n,rest:restDist})}}function simulate(a){const c=windLevel*.4+gustPower;gustPower*=.96;for(const n of particles){if(n.pinned||n.dragging)continue;const e=(n.x-n.ox)*DAMPING,o=(n.y-n.oy)*DAMPING;n.ox=n.x,n.oy=n.y;const t=c*(Math.sin(a*2+n.y*.01)*.7+Math.sin(a*4.3+n.x*.02)*.3),i=c*Math.sin(a*1.8+n.x*.015)*.12;n.x+=e+t,n.y+=o+GRAVITY+i}for(let n=0;n<ITERS;n++)for(const e of constraints){const o=particles[e.a],t=particles[e.b],i=t.x-o.x,l=t.y-o.y,r=Math.sqrt(i*i+l*l);if(r<.001)continue;const d=(r-e.rest)/r*.5;!o.pinned&&!o.dragging&&(o.x+=i*d,o.y+=l*d),!t.pinned&&!t.dragging&&(t.x-=i*d,t.y-=l*d)}}function texTri(a,c,n,e,o,t,i,l,r,d,f,h,g){const s=c*(o-i)+e*(i-n)+t*(n-o);if(Math.abs(s)<.01)return;const m=(l*(o-i)+d*(i-n)+h*(n-o))/s,u=(r*(o-i)+f*(i-n)+g*(n-o))/s,p=(l*(t-e)+d*(c-t)+h*(e-c))/s,w=(r*(t-e)+f*(c-t)+g*(e-c))/s,b=(l*(e*i-t*o)+d*(t*n-c*i)+h*(c*o-e*n))/s,v=(r*(e*i-t*o)+f*(t*n-c*i)+g*(c*o-e*n))/s;ctx.save(),ctx.beginPath(),ctx.moveTo(l,r),ctx.lineTo(d,f),ctx.lineTo(h,g),ctx.closePath(),ctx.clip(),ctx.setTransform(m,u,p,w,b,v),ctx.drawImage(a,0,0),ctx.restore()}function renderCloth(){const a=COLS+1;for(let c=0;c<ROWS;c++)for(let n=0;n<COLS;n++){const e=cellImages[c*COLS+n];if(!e)continue;const o=particles[c*a+n],t=particles[c*a+n+1],i=particles[(c+1)*a+n],l=particles[(c+1)*a+n+1],r=e.width,d=e.height;texTri(e,0,0,r,0,0,d,o.x,o.y,t.x,t.y,i.x,i.y),texTri(e,r,0,r,d,0,d,t.x,t.y,l.x,l.y,i.x,i.y)}}function drawPole(){const a=particles[0],c=particles[ROWS*(COLS+1)];ctx.strokeStyle="#555",ctx.lineWidth=6,ctx.lineCap="round",ctx.beginPath(),ctx.moveTo(a.x-4,a.y-20),ctx.lineTo(c.x-4,c.y+20),ctx.stroke(),ctx.fillStyle="#777",ctx.beginPath(),ctx.arc(a.x-4,a.y-24,6,0,6.283),ctx.fill()}async function init(){buildCloth();const a=COLS*ROWS,e=(await(await fetch("/api/thumbnails?offset=0&limit="+a)).json()).items.filter(t=>t.thumbnailId);for(let t=e.length-1;t>0;t--){const i=Math.floor(Math.random()*(t+1));[e[t],e[i]]=[e[i],e[t]]}const o=[];for(let t=0;t<a;t++){const i=e[t%e.length];o.push(new Promise(l=>{const r=new Image;r.onload=()=>l(r),r.onerror=()=>l(null),r.src="/api/thumbnail/"+i.thumbnailId}))}cellImages=(await Promise.all(o)).filter(Boolean),document.getElementById("loading").classList.add("hidden"),requestAnimationFrame(animate)}function animate(a){const c=a/1e3,n=canvas.width,e=canvas.height;simulate(c),ctx.clearRect(0,0,n,e);const o=ctx.createRadialGradient(n*.6,e*.4,0,n*.6,e*.4,n*.7);o.addColorStop(0,"#161620"),o.addColorStop(1,"#111"),ctx.fillStyle=o,ctx.fillRect(0,0,n,e),drawPole(),ctx.setTransform(1,0,0,1,0,0),renderCloth(),ctx.setTransform(1,0,0,1,0,0),requestAnimationFrame(animate)}canvas.addEventListener("mousedown",a=>{const c=a.clientX,n=a.clientY;let e=50,o=-1;for(let t=0;t<particles.length;t++){const i=Math.hypot(particles[t].x-c,particles[t].y-n);i<e&&(e=i,o=t)}o>=0&&!particles[o].pinned&&(dragIdx=o,particles[o].dragging=!0)}),canvas.addEventListener("mousemove",a=>{dragIdx>=0&&(particles[dragIdx].x=a.clientX,particles[dragIdx].y=a.clientY)}),canvas.addEventListener("mouseup",()=>{dragIdx>=0&&(particles[dragIdx].dragging=!1,dragIdx=-1)}),canvas.addEventListener("touchstart",a=>{const c=a.touches[0],n=c.clientX,e=c.clientY;let o=60,t=-1;for(let i=0;i<particles.length;i++){const l=Math.hypot(particles[i].x-n,particles[i].y-e);l<o&&(o=l,t=i)}t>=0&&!particles[t].pinned&&(dragIdx=t,particles[t].dragging=!0),a.preventDefault()},{passive:!1}),canvas.addEventListener("touchmove",a=>{if(dragIdx>=0){const c=a.touches[0];particles[dragIdx].x=c.clientX,particles[dragIdx].y=c.clientY}a.preventDefault()},{passive:!1}),canvas.addEventListener("touchend",()=>{dragIdx>=0&&(particles[dragIdx].dragging=!1,dragIdx=-1)}),document.getElementById("windDown").onclick=()=>{windLevel=Math.max(0,windLevel-1),document.getElementById("windEl").textContent=windLevel},document.getElementById("windUp").onclick=()=>{windLevel=Math.min(6,windLevel+1),document.getElementById("windEl").textContent=windLevel},document.getElementById("gustBtn").onclick=()=>{gustPower=8},window.addEventListener("resize",()=>{canvas.width=window.innerWidth,canvas.height=window.innerHeight,buildCloth()}),init();