Show code
<!doctype html><html><head><meta charset="utf-8"><title>Linked List</title><style>html,body{margin:0;height:100%;background:#0f1424;overflow:hidden}canvas{display:block}</style></head><body><canvas id="c"></canvas><script>
const cv=document.getElementById('c'),g=cv.getContext('2d');
const BW=58,BH=34,GX=104,GY=92,X0=36,Y0=110,HL=.7,SW=1.1,MV=.7;
let W,H,nd=[],ph='wait',tm=.8,op=null,e1=0,e2=0;
const R=n=>Math.random()*n|0,ease=t=>t*t*(3-2*t),lp=(a,b,t)=>a+(b-a)*t;
function mk(){return{v:R(90)+10,x:0,y:0,tx:0,ty:0,a:1}}
function lay(s){const per=Math.max(2,(W-X0*2)/GX|0);nd.forEach((n,i)=>{n.tx=X0+(i%per)*GX;n.ty=Y0+((i/per)|0)*GY;if(s){n.x=n.tx;n.y=n.ty}})}
function rs(){W=cv.width=innerWidth;H=cv.height=innerHeight;lay(0)}
addEventListener('resize',rs);
function fresh(){nd=[];const c=3+R(3);for(let i=0;i<c;i++)nd.push(mk());lay(1);ph='wait';tm=1;op=null}
rs();fresh();
function start(){
const L=nd.length;
if(L>=9||L==0){fresh();return}
const ins=Math.random()<(L<3?.85:L>7?.15:.55);
if(ins){
const i=R(L+1),n=mk(),p=nd[i-1],s=nd[i],r=s||p;
n.a=0;n.x=n.tx=s?s.tx:Math.min(p.tx+GX,W-BW-20);n.y=n.ty=r.ty-56;
op={type:'i',i,p,s,n,t:0};
}else{
const i=R(L);
op={type:'d',i,p:nd[i-1],n:nd[i],s:nd[i+1],t:0};
}
ph='hl';
}
function step(dt){
nd.forEach(n=>{const k=Math.min(1,dt*7);n.x+=(n.tx-n.x)*k;n.y+=(n.ty-n.y)*k});
e1=0;e2=0;
if(ph=='wait'){tm-=dt;if(tm<=0)start()}
else if(ph=='hl'){op.t+=dt;if(op.type=='i')op.n.a=Math.min(1,op.t/HL);if(op.t>=HL){ph='sw';op.t=0}}
else if(ph=='sw'){op.t+=dt;const tt=Math.min(1,op.t/SW);
if(op.type=='i'){e1=ease(Math.min(1,tt*1.7));e2=ease(Math.max(0,(tt-.45)/.55))}
else{e1=ease(tt);op.n.a=1-e1}
if(op.t>=SW){if(op.type=='i')nd.splice(op.i,0,op.n);else nd.splice(op.i,1);lay(0);ph='mv';op.t=0}}
else if(ph=='mv'){op.t+=dt;if(op.t>=MV){ph='wait';tm=.8+Math.random();op=null}}
}
function arr(x1,y1,x2,y2,a,c){
const dx=x2-x1,dy=y2-y1,L=Math.hypot(dx,dy)||1,ux=dx/L,uy=dy/L;
g.globalAlpha=Math.max(0,a);g.strokeStyle=c;g.fillStyle=c;g.lineWidth=2;
g.beginPath();g.moveTo(x1,y1);g.lineTo(x2,y2);g.stroke();
g.beginPath();g.moveTo(x2,y2);g.lineTo(x2-ux*10-uy*5,y2-uy*10+ux*5);g.lineTo(x2-ux*10+uy*5,y2-uy*10-ux*5);g.closePath();g.fill();
g.globalAlpha=1;
}
function box(n,h){
g.globalAlpha=Math.max(0,n.a);
g.fillStyle='#1d2742';g.fillRect(n.x,n.y,BW,BH);
g.strokeStyle=h?'#ffd166':'#6e8efb';g.lineWidth=h?3:2;g.strokeRect(n.x,n.y,BW,BH);
g.fillStyle='#e8ecff';g.font='13px monospace';g.textAlign='center';g.textBaseline='middle';
g.fillText(n.v,n.x+BW/2,n.y+BH/2+1);g.globalAlpha=1;
}
function headM(x,y,a){
g.globalAlpha=Math.max(0,a);g.fillStyle='#3ddc84';
g.beginPath();g.moveTo(x+BW/2,y-5);g.lineTo(x+BW/2-7,y-17);g.lineTo(x+BW/2+7,y-17);g.closePath();g.fill();
g.font='bold 12px monospace';g.textAlign='center';g.textBaseline='alphabetic';
g.fillText('HEAD',x+BW/2,y-22);g.globalAlpha=1;
}
const EP=n=>[n.x,n.y+BH/2],SP=n=>[n.x+BW,n.y+BH/2];
function draw(){
g.fillStyle='#0f1424';g.fillRect(0,0,W,H);
g.fillStyle='#9fb0d8';g.font='16px monospace';g.textAlign='left';g.textBaseline='alphabetic';
g.fillText('singly linked list — length: '+nd.length,20,34);
if(op)g.fillText((op.type=='i'?'inserting at ':'deleting at ')+op.i,20,58);
const anim=op&&(ph=='hl'||ph=='sw');
for(let i=0;i<nd.length-1;i++){
const c=nd[i],x=nd[i+1];
if(anim&&c==op.p)continue;
const[a1,b1]=SP(c),[a2,b2]=EP(x);
arr(a1,b1,a2,b2,Math.min(c.a,x.a),'#8ea0d0');
}
if(anim){
const P=op.p,S=op.s,N=op.n;
if(P){
const[a1,b1]=SP(P);let x0,y0,x1,y1;
if(op.type=='i'){[x0,y0]=S?EP(S):[a1,b1];[x1,y1]=EP(N)}
else{[x0,y0]=EP(N);[x1,y1]=S?EP(S):[a1,b1]}
const tx=lp(x0,x1,e1),ty=lp(y0,y1,e1);
if(Math.hypot(tx-a1,ty-b1)>5)arr(a1,b1,tx,ty,1,'#ffd166');
}
if(op.type=='i'&&S&&e2>0){
const[a1,b1]=SP(N),[x1,y1]=EP(S);
arr(a1,b1,lp(a1,x1,e2),lp(b1,y1,e2),Math.min(1,op.n.a),'#ffd166');
}
}
nd.forEach(n=>box(n,anim&&(n==op.p||n==op.s||n==op.n)));
if(anim&&op.type=='i')box(op.n,1);
let hx=null,hy=0,ha=1;
if(anim&&!op.p){
if(op.type=='i'){hx=lp(op.s.x,op.n.x,e1);hy=lp(op.s.y,op.n.y,e1)}
else if(op.s){hx=lp(op.n.x,op.s.x,e1);hy=lp(op.n.y,op.s.y,e1)}
else{hx=op.n.x;hy=op.n.y;ha=op.n.a}
}else if(nd[0]){hx=nd[0].x;hy=nd[0].y}
if(hx!=null)headM(hx,hy,ha);
}
let lt=0;
function frame(ts){
const dt=Math.min(.05,(ts-lt)/1000||0);lt=ts;
step(dt);draw();requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
</script></body></html>