asciify-engine 1.0.5 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/embed.js ADDED
@@ -0,0 +1 @@
1
+ (function(){'use strict';function fn(o,p,n){let e=t=>{let a=atob(t),f=new Uint8Array(a.length);for(let M=0;M<a.length;M++)f[M]=a.charCodeAt(M);return f};return Array.isArray(o)?o.map(e):[e(o)]}function mn(o,p,n,e){let t=(n*e+p)*5;return {r:o[t],g:o[t+1],b:o[t+2],a:o[t+3],l:o[t+4]}}function Mn(o){return o*o*(3-2*o)}function gn(o,p){if(o==="fullcolor")return (n,e,t)=>`rgb(${n},${e},${t})`;if(o==="matrix")return (n,e,t)=>`rgb(0,${Math.floor(.299*n+.587*e+.114*t)},0)`;if(o==="accent"){let n=p.replace("#",""),e=parseInt(n.substring(0,2),16),t=parseInt(n.substring(2,4),16),a=parseInt(n.substring(4,6),16);return (f,M,c)=>{let r=(.299*f+.587*M+.114*c)/255;return `rgb(${Math.floor(e*r)},${Math.floor(t*r)},${Math.floor(a*r)})`}}return (n,e,t)=>{let a=Math.floor(.299*n+.587*e+.114*t);return `rgb(${a},${a},${a})`}}function bn(o,p,n,e,t,a,f){let M=p,c=f*M;switch(o){case "wave":{let r=Math.sin(n/t*Math.PI*4+c*3)*.5+.5,s=Math.sin(e/a*Math.PI*3+c*2)*.5+.5;return .3+.7*(r*.6+s*.4)}case "pulse":{let r=t/2,s=a/2,m=Math.sqrt((n-r)**2+(e-s)**2),h=Math.sqrt(r*r+s*s);return .2+.8*(Math.sin(m/h*Math.PI*6-c*4)*.5+.5)}case "rain":return .1+.9*(Math.sin(e/a*Math.PI*8-c*5+n*.3)*.5+.5)*(Math.sin(n/t*Math.PI*2+c)*.3+.7);case "breathe":return Math.max(.1,Math.min(1,Math.sin(c*2)*.3+.7+Math.sin((n+e)*.1+c)*.1));case "sparkle":{let r=Math.sin(n*127.1+e*311.7+Math.floor(c*8)*43758.5453)*43758.5453,s=r-Math.floor(r);return s>.7?1:.15+s*.4}case "glitch":{let r=Math.floor(e/(a*.05)),s=Math.sin(r*43.23+Math.floor(c*6)*17.89)*43758.5453;if(s-Math.floor(s)>.85){let h=Math.sin(c*30+r)*.5+.5;return h<.3?0:h}return 1}case "spiral":{let r=t/2,s=a/2,m=n-r,h=e-s,g=Math.atan2(h,m),$=Math.sqrt(m*m+h*h),k=Math.sqrt(r*r+s*s);return .15+.85*(Math.sin(g*3+$/k*Math.PI*8-c*3)*.5+.5)}case "typewriter":{let r=t*a,s=e*t+n,m=c*.5%1,h=m*r*1.3,g=s-h;return g>0?0:Math.min(1,Math.max(0,1+g/(r*.15)))}case "scatter":{let r=t/2,s=a/2,m=n-r,h=e-s,g=Math.sqrt(m*m+h*h)/Math.sqrt(r*r+s*s),$=Math.sin(c*1.5)*.5+.5;return g>$?Math.max(0,1-(g-$)*3):.7+.3*Math.sin(g*10-c*2)}default:return 1}}function dn(o,p,n){let e=document.getElementById(o);if(!e){console.error(`Asciify: canvas #${o} not found`);return}let t=e.getContext("2d"),{r:a,c:f,w:M,h:c}=n,r=n.fps??10,s=n.cs??" .:-=+*#%@",m=n.cm??"grayscale",h=n.ac??"#ffffff",g=n.as??"none",$=n.sp??1,k=n.inv??false,l=n.hs??0,en=n.hr??.3,E=n.he??"spotlight",T=n.hc??"#ffffff",rn=n.dr??.7,sn=n.dots??false,K=n.anim??false,an=parseInt(T.slice(1,3),16)||255,on=parseInt(T.slice(3,5),16)||255,cn=parseInt(T.slice(5,7),16)||255,I=M/f,w=c/a,N=fn(p),hn=gn(m,h),B=l>0,Q=g!=="none"||K,L=-1,U=-1,v=0,W=.5,X=.5,Y=0,V=0;B&&(e.addEventListener("mousemove",q=>{let P=e.getBoundingClientRect();L=(q.clientX-P.left)/P.width,U=(q.clientY-P.top)/P.height;}),e.addEventListener("mouseleave",()=>{L=-1,U=-1;}));function D(q){let P=q/1e3;K&&q-V>=1e3/r&&(Y=(Y+1)%N.length,V=q);let ln=N[Y];t.clearRect(0,0,M,c),t.fillStyle="#0a0a0a",t.fillRect(0,0,M,c),B&&(L>=0?(W+=(L-W)*.1,X+=(U-X)*.1,v+=(1-v)*.12):(v*=.96,v<.003&&(v=0)));for(let R=0;R<a;R++)for(let S=0;S<f;S++){let x=mn(ln,S,R,f);if(x.a<10)continue;let G=bn(g,$,S,R,f,a,P);if(G<.05)continue;let C=1,J=0,j=0,F=0,A=0;if(B&&v>.003){let u=S/f,b=R/a,d=u-W,y=b-X,nn=Math.sqrt(d*d+y*y),tn=.08+en*.35+l*.04;if(nn<tn){let un=1-nn/tn,i=Mn(un)*v,O=Math.atan2(y,d);if(E==="spotlight"){C=1+i*l*1.8;let H=i*i*l*.6;J=Math.cos(O)*H*I,j=Math.sin(O)*H*w,F=i*l*.4,A=i*i*l*.25;}else if(E==="magnify")C=1+i*l*2.5,F=i*l*.15;else if(E==="repel"){C=1+i*l*.3;let H=i*i*l*1.2;J=Math.cos(O)*H*I,j=Math.sin(O)*H*w;}else E==="glow"?(F=i*l*.8,A=i*l*.4):E==="colorShift"&&(C=1+i*l*.4,F=i*l*.2,A=i*l*.7);}}let Z=S*I+I/2+J,_=R*w+w/2+j,z=hn(x.r,x.g,x.b);if(A>0){let u=z.match(/rgb\((\d+),(\d+),(\d+)\)/);if(u){let b=+u[1],d=+u[2],y=+u[3];z=`rgb(${Math.min(255,Math.round(b+(an-b)*A))},${Math.min(255,Math.round(d+(on-d)*A))},${Math.min(255,Math.round(y+(cn-y)*A))})`;}}if(t.globalAlpha=Math.min(1,x.a/255*G*(1+F)),t.fillStyle=z,sn){let u=x.l/255;if(k&&(u=1-u),u<.02)continue;let b=Math.min(I,w)*.5*rn*u*G*C;if(b<.3)continue;t.beginPath(),t.arc(Z,_,b,0,Math.PI*2),t.fill();}else {let u=x.l/255;k&&(u=1-u);let b=Math.floor(u*(s.length-1)),d=s[Math.max(0,Math.min(s.length-1,b))];if(d===" ")continue;let y=Math.min(I/.55,w)*.9*C;t.font=`${y}px "JetBrains Mono",monospace`,t.textAlign="center",t.textBaseline="middle",t.fillText(d,Z,_);}}t.globalAlpha=1,(Q||B)&&requestAnimationFrame(D);}Q||B?requestAnimationFrame(D):D(0);}window.Asciify=dn;})();
package/dist/index.cjs CHANGED
@@ -276,6 +276,8 @@ function getAnimationMultiplier(x, y, cols, rows, time, style, speed) {
276
276
  }
277
277
  return 0.7 + 0.3 * Math.sin(sdist * 10 - t * 2);
278
278
  }
279
+ case "waveField":
280
+ return 1;
279
281
  default:
280
282
  return 1;
281
283
  }
@@ -468,6 +470,24 @@ function computeHoverEffect(nx, ny, hoverX, hoverY, hoverIntensity, strength, ce
468
470
  return _hoverResult;
469
471
  }
470
472
  function renderFrameToCanvas(ctx, frame, options, canvasWidth, canvasHeight, time = 0, hoverPos) {
473
+ if (options.animationStyle === "waveField") {
474
+ const mouseNorm = hoverPos ? { x: hoverPos.x, y: hoverPos.y } : { x: 0.5, y: 0.5 };
475
+ const acHexWF = (options.accentColor || "#d4ff00").replace("#", "");
476
+ parseInt(acHexWF.substring(0, 2), 16) || 212;
477
+ parseInt(acHexWF.substring(2, 4), 16) || 255;
478
+ parseInt(acHexWF.substring(4, 6), 16) || 0;
479
+ renderWaveBackground(ctx, canvasWidth, canvasHeight, time, mouseNorm, {
480
+ accentColor: `#${acHexWF}`,
481
+ accentThreshold: 0.52,
482
+ mouseInfluence: options.hoverStrength > 0 ? Math.min(1, 0.3 + options.hoverStrength * 0.5) : 0.55,
483
+ mouseFalloff: 2.8,
484
+ speed: options.animationSpeed,
485
+ vortex: options.hoverStrength > 0,
486
+ sparkles: true,
487
+ breathe: true
488
+ });
489
+ return;
490
+ }
471
491
  const rows = frame.length;
472
492
  if (rows === 0) return;
473
493
  const cols = frame[0].length;
@@ -700,36 +720,27 @@ function renderFrameToCanvas(ctx, frame, options, canvasWidth, canvasHeight, tim
700
720
  ctx.globalAlpha = 1;
701
721
  }
702
722
  function serializeFrame(frame, includeChars) {
703
- return frame.map((row) => row.map((cell) => {
704
- const obj = { r: cell.r, g: cell.g, b: cell.b, a: cell.a };
705
- if (includeChars) obj.c = cell.char.charCodeAt(0);
706
- else obj.l = Math.round(0.299 * cell.r + 0.587 * cell.g + 0.114 * cell.b);
707
- return obj;
708
- }));
709
- }
710
- function buildAnimFnJS(style, speed) {
711
- if (style === "none") return "function(){return 1}";
712
- return `function(x,y,cols,rows,t){
713
- var s=${speed},T=t*s;
714
- ${style === "wave" ? `var w=Math.sin(x/cols*Math.PI*4+T*3)*.5+.5,w2=Math.sin(y/rows*Math.PI*3+T*2)*.5+.5;return .3+.7*(w*.6+w2*.4);` : ""}${style === "pulse" ? `var cx=cols/2,cy=rows/2,d=Math.sqrt((x-cx)*(x-cx)+(y-cy)*(y-cy)),m=Math.sqrt(cx*cx+cy*cy);return .2+.8*(Math.sin(d/m*Math.PI*6-T*4)*.5+.5);` : ""}${style === "rain" ? `return .1+.9*(Math.sin(y/rows*Math.PI*8-T*5+x*.3)*.5+.5)*(Math.sin(x/cols*Math.PI*2+T)*.3+.7);` : ""}${style === "breathe" ? `return Math.max(.1,Math.min(1,Math.sin(T*2)*.3+.7+Math.sin((x+y)*.1+T)*.1));` : ""}${style === "sparkle" ? `var h=Math.sin(x*127.1+y*311.7+Math.floor(T*8)*43758.5453)*43758.5453;var sp=h-Math.floor(h);return sp>.7?1:.15+sp*.4;` : ""}${style === "glitch" ? `var b=Math.floor(y/(rows*.05)),gh=Math.sin(b*43.23+Math.floor(T*6)*17.89)*43758.5453,gv=gh-Math.floor(gh);if(gv>.85){var fl=Math.sin(T*30+b)*.5+.5;return fl<.3?0:fl}return 1;` : ""}${style === "spiral" ? `var cx=cols/2,cy=rows/2,dx=x-cx,dy=y-cy,a=Math.atan2(dy,dx),d=Math.sqrt(dx*dx+dy*dy),m=Math.sqrt(cx*cx+cy*cy);return .15+.85*(Math.sin(a*3+d/m*Math.PI*8-T*3)*.5+.5);` : ""}${style === "typewriter" ? `var tc=cols*rows,ci=y*cols+x,p=(T*.5)%1,rp=p*tc*1.3,dd=ci-rp;if(dd>0)return 0;return Math.min(1,Math.max(0,1+dd/(tc*.15)));` : ""}${style === "scatter" ? `var cx=cols/2,cy=rows/2,dx=x-cx,dy=y-cy,sd=Math.sqrt(dx*dx+dy*dy)/Math.sqrt(cx*cx+cy*cy),ph=Math.sin(T*1.5)*.5+.5;if(sd>ph)return Math.max(0,1-(sd-ph)*3);return .7+.3*Math.sin(sd*10-T*2);` : ""}
715
- }`;
716
- }
717
- function buildColorFnJS(options) {
718
- switch (options.colorMode) {
719
- case "fullcolor":
720
- return `function(c){return 'rgb('+c.r+','+c.g+','+c.b+')'}`;
721
- case "matrix":
722
- return `function(c){var b=Math.floor(.299*c.r+.587*c.g+.114*c.b);return 'rgb(0,'+b+',0)'}`;
723
- case "accent": {
724
- const hex = options.accentColor.replace("#", "");
725
- const ar = parseInt(hex.substring(0, 2), 16);
726
- const ag = parseInt(hex.substring(2, 4), 16);
727
- const ab = parseInt(hex.substring(4, 6), 16);
728
- return `function(c){var b=(.299*c.r+.587*c.g+.114*c.b)/255;return 'rgb('+Math.floor(${ar}*b)+','+Math.floor(${ag}*b)+','+Math.floor(${ab}*b)+')'}`;
723
+ const rows = frame.length;
724
+ const cols = rows > 0 ? frame[0].length : 0;
725
+ const buf = new Uint8Array(rows * cols * 5);
726
+ let i = 0;
727
+ for (let y = 0; y < rows; y++) {
728
+ for (let x = 0; x < cols; x++) {
729
+ const cell = frame[y][x];
730
+ buf[i++] = cell.r;
731
+ buf[i++] = cell.g;
732
+ buf[i++] = cell.b;
733
+ buf[i++] = cell.a;
734
+ if (includeChars) {
735
+ buf[i++] = cell.char.charCodeAt(0) & 255;
736
+ } else {
737
+ buf[i++] = Math.round(0.299 * cell.r + 0.587 * cell.g + 0.114 * cell.b);
738
+ }
729
739
  }
730
- default:
731
- return `function(c){var g=Math.floor(.299*c.r+.587*c.g+.114*c.b);return 'rgb('+g+','+g+','+g+')'}`;
732
740
  }
741
+ let binary = "";
742
+ for (let j = 0; j < buf.length; j++) binary += String.fromCharCode(buf[j]);
743
+ return btoa(binary);
733
744
  }
734
745
  async function asciify(source, canvas, { fontSize = 10, style = "classic", options = {} } = {}) {
735
746
  let el;
@@ -821,188 +832,171 @@ async function asciifyVideo(source, canvas, { fontSize = 10, style = "classic",
821
832
  cancelAnimationFrame(animId);
822
833
  };
823
834
  }
835
+ var EMBED_CDN_VERSION = "1.0.5";
836
+ function buildEmbedOpts(options, rows, cols, width, height, fps, animated) {
837
+ const o = {
838
+ r: rows,
839
+ c: cols,
840
+ w: width,
841
+ h: height,
842
+ cs: options.charset,
843
+ cm: options.colorMode,
844
+ as: options.animationStyle,
845
+ sp: options.animationSpeed,
846
+ inv: options.invert,
847
+ hs: options.hoverStrength,
848
+ hr: options.hoverRadius,
849
+ he: options.hoverEffect,
850
+ hc: options.hoverColor,
851
+ dr: options.dotSizeRatio,
852
+ dots: options.renderMode === "dots"
853
+ };
854
+ if (options.colorMode === "accent") o.ac = options.accentColor;
855
+ if (fps !== void 0) o.fps = fps;
856
+ if (animated) o.anim = true;
857
+ return JSON.stringify(o);
858
+ }
824
859
  function generateEmbedCode(frame, options, width, height) {
825
860
  const rows = frame.length;
826
861
  if (rows === 0) return "";
827
862
  const cols = frame[0].length;
828
863
  const isDots = options.renderMode === "dots";
829
864
  const data = serializeFrame(frame, !isDots);
830
- const hasAnim = options.animationStyle !== "none";
831
- const hasHover = options.hoverStrength > 0;
832
- const charset = isDots ? "" : options.charset;
833
- const hc = options.hoverColor || "#ffffff";
834
- const hcR = parseInt(hc.slice(1, 3), 16) || 255;
835
- const hcG = parseInt(hc.slice(3, 5), 16) || 255;
836
- const hcB = parseInt(hc.slice(5, 7), 16) || 255;
837
- const hasTransparency = frame.some((row) => row.some((cell) => cell.a < 200));
865
+ const id = `ar-${Math.random().toString(36).slice(2, 9)}`;
866
+ const opts = buildEmbedOpts(options, rows, cols, width, height);
838
867
  return `<!-- Asciify Embed -->
839
- <canvas id="ar-embed" width="${width}" height="${height}" style="${hasTransparency ? "" : "background:#0a0a0a;"}display:block;"></canvas>
840
- <script>
841
- (function(){
842
- var D=${JSON.stringify(data)};
843
- var R=${rows},C=${cols},W=${width},H=${height};
844
- var cW=W/C,cH=H/R;
845
- var isDots=${isDots};
846
- var invert=${options.invert};
847
- var dotR=${options.dotSizeRatio};
848
- var hStr=${options.hoverStrength},hRad=${options.hoverRadius};
849
- var hcR=${hcR},hcG=${hcG},hcB=${hcB};
850
- var hEff='${options.hoverEffect}';
851
- var charset=${JSON.stringify(charset)};
852
- var hasTr=${hasTransparency};
853
- var cv=document.getElementById('ar-embed'),ctx=cv.getContext('2d');
854
- var mx=-1,my=-1,mIn=0;
855
- var getColor=${buildColorFnJS(options)};
856
- var getAnim=${buildAnimFnJS(options.animationStyle, options.animationSpeed)};
857
- ${hasHover ? `
858
- cv.addEventListener('mousemove',function(e){var r=cv.getBoundingClientRect();mx=(e.clientX-r.left)/r.width;my=(e.clientY-r.top)/r.height});
859
- cv.addEventListener('mouseleave',function(){mx=-1;my=-1});
860
- function ss(t){return t*t*(3-2*t)}
861
- ` : ""}
862
- var smX=.5,smY=.5;
863
- function draw(t){
864
- var time=t/1000;
865
- ctx.clearRect(0,0,W,H);
866
- if(!hasTr){ctx.fillStyle='#0a0a0a';ctx.fillRect(0,0,W,H)};
867
- ${hasHover ? `
868
- if(mx>=0){smX+=(mx-smX)*.1;smY+=(my-smY)*.1;mIn+=(1-mIn)*.12}
869
- else{mIn*=.96;if(mIn<.003)mIn=0}
870
- ` : ""}
871
- for(var y=0;y<R;y++)for(var x=0;x<C;x++){
872
- var p=D[y][x];if(p.a<10)continue;
873
- var am=getAnim(x,y,C,R,time);if(am<.05)continue;
874
- var sc=1,ox=0,oy=0,gl=0,cb=0;
875
- ${hasHover ? `
876
- if(mIn>.003&&hStr>0){
877
- var nx=x/C,ny=y/R,dx=nx-smX,dy=ny-smY,dd=Math.sqrt(dx*dx+dy*dy);
878
- var rad=(.08+hRad*.35)+hStr*.04;
879
- if(dd<rad){
880
- var tt=1-dd/rad,e=ss(tt)*mIn,ang=Math.atan2(dy,dx);
881
- if(hEff==='spotlight'){sc=1+e*hStr*1.8;var pf=e*e*hStr*.6;ox=Math.cos(ang)*pf*cW;oy=Math.sin(ang)*pf*cH;gl=e*hStr*.4;cb=e*e*hStr*.25}
882
- else if(hEff==='magnify'){sc=1+e*hStr*2.5;gl=e*hStr*.15}
883
- else if(hEff==='repel'){sc=1+e*hStr*.3;var pf=e*e*hStr*1.2;ox=Math.cos(ang)*pf*cW;oy=Math.sin(ang)*pf*cH}
884
- else if(hEff==='glow'){gl=e*hStr*.8;cb=e*hStr*.4}
885
- else if(hEff==='colorShift'){sc=1+e*hStr*.4;gl=e*hStr*.2;cb=e*hStr*.7}
886
- }
887
- }
888
- ` : ""}
889
- var px=x*cW+cW/2+ox,py=y*cH+cH/2+oy;
890
- var col=getColor(p);
891
- if(cb>0){var m=col.match(/rgb\\((\\d+),(\\d+),(\\d+)\\)/);if(m){var rr=+m[1],gg=+m[2],bb=+m[3];col='rgb('+Math.min(255,Math.round(rr+(hcR-rr)*cb))+','+Math.min(255,Math.round(gg+(hcG-gg)*cb))+','+Math.min(255,Math.round(bb+(hcB-bb)*cb))+')'}}
892
- if(isDots){
893
- var lum=p.l/255;var int=invert?1-lum:lum;if(int<.02)continue;
894
- var rad=Math.min(cW,cH)*.5*dotR*int*am*sc;if(rad<.3)continue;
895
- ctx.globalAlpha=Math.min(1,(p.a/255)*am*(1+gl));
896
- ctx.fillStyle=col;ctx.beginPath();ctx.arc(px,py,rad,0,Math.PI*2);ctx.fill()
897
- }else{
898
- var lum=(.299*p.r+.587*p.g+.114*p.b)/255;if(invert)lum=1-lum;
899
- var ci=Math.floor(lum*(charset.length-1));
900
- var ch=charset[Math.max(0,Math.min(charset.length-1,ci))];
901
- if(ch===' ')continue;
902
- ctx.globalAlpha=Math.min(1,(p.a/255)*am*(1+gl));
903
- ctx.fillStyle=col;
904
- var fs=Math.min(cW/.55,cH)*.9*sc;
905
- ctx.font=fs+'px "JetBrains Mono",monospace';ctx.textAlign='center';ctx.textBaseline='middle';
906
- ctx.fillText(ch,px,py)
907
- }
908
- }
909
- ctx.globalAlpha=1;
910
- ${hasAnim || hasHover ? "requestAnimationFrame(draw)" : ""};
911
- }
912
- ${hasAnim || hasHover ? "requestAnimationFrame(draw)" : "draw(0)"};
913
- })();
914
- </script>
868
+ <canvas id="${id}" width="${width}" height="${height}" style="display:block"></canvas>
869
+ <script src="https://cdn.jsdelivr.net/npm/asciify-engine@${EMBED_CDN_VERSION}/dist/embed.js"></script>
870
+ <script>Asciify('${id}','${data}',${opts})</script>
915
871
  <!-- /Asciify Embed -->`;
916
872
  }
917
873
  function generateAnimatedEmbedCode(frames, options, fps, width, height) {
874
+ if (frames.length === 0) return "";
918
875
  const rows = frames[0].length;
919
876
  const cols = frames[0][0].length;
920
877
  const isDots = options.renderMode === "dots";
921
878
  const allData = frames.map((f) => serializeFrame(f, !isDots));
922
- const hasHover = options.hoverStrength > 0;
923
- const hc = options.hoverColor || "#ffffff";
924
- const hcR = parseInt(hc.slice(1, 3), 16) || 255;
925
- const hcG = parseInt(hc.slice(3, 5), 16) || 255;
926
- const hcB = parseInt(hc.slice(5, 7), 16) || 255;
927
- const charset = isDots ? "" : options.charset;
928
- const hasTransparency = frames.some((f) => f.some((row) => row.some((cell) => cell.a < 200)));
879
+ const id = `ar-${Math.random().toString(36).slice(2, 9)}`;
880
+ const opts = buildEmbedOpts(options, rows, cols, width, height, fps, true);
929
881
  return `<!-- Asciify Animated Embed -->
930
- <canvas id="ar-anim" width="${width}" height="${height}" style="${hasTransparency ? "" : "background:#0a0a0a;"}display:block;"></canvas>
931
- <script>
932
- (function(){
933
- var F=${JSON.stringify(allData)};
934
- var R=${rows},C=${cols},W=${width},H=${height},FPS=${fps};
935
- var cW=W/C,cH=H/R;
936
- var isDots=${isDots};
937
- var invert=${options.invert};
938
- var dotR=${options.dotSizeRatio};
939
- var hStr=${options.hoverStrength},hRad=${options.hoverRadius};
940
- var hcR=${hcR},hcG=${hcG},hcB=${hcB};
941
- var hEff='${options.hoverEffect}';
942
- var charset=${JSON.stringify(charset)};
943
- var hasTr=${hasTransparency};
944
- var cv=document.getElementById('ar-anim'),ctx=cv.getContext('2d');
945
- var mx=-1,my=-1,mIn=0,smX=.5,smY=.5;
946
- var fi=0,lastT=0;
947
- var getColor=${buildColorFnJS(options)};
948
- ${hasHover ? `
949
- cv.addEventListener('mousemove',function(e){var r=cv.getBoundingClientRect();mx=(e.clientX-r.left)/r.width;my=(e.clientY-r.top)/r.height});
950
- cv.addEventListener('mouseleave',function(){mx=-1;my=-1});
951
- function ss(t){return t*t*(3-2*t)}
952
- ` : ""}
953
- function draw(t){
954
- var time=t/1000;
955
- if(t-lastT>=1000/FPS){fi=(fi+1)%F.length;lastT=t}
956
- var D=F[fi];
957
- ctx.clearRect(0,0,W,H);if(!hasTr){ctx.fillStyle='#0a0a0a';ctx.fillRect(0,0,W,H)};
958
- ${hasHover ? `
959
- if(mx>=0){smX+=(mx-smX)*.1;smY+=(my-smY)*.1;mIn+=(1-mIn)*.12}
960
- else{mIn*=.96;if(mIn<.003)mIn=0}
961
- ` : ""}
962
- for(var y=0;y<R;y++)for(var x=0;x<C;x++){
963
- var p=D[y][x];if(p.a<10)continue;
964
- var sc=1,ox=0,oy=0,gl=0,cb=0;
965
- ${hasHover ? `
966
- if(mIn>.003&&hStr>0){
967
- var nx=x/C,ny=y/R,dx=nx-smX,dy=ny-smY,dd=Math.sqrt(dx*dx+dy*dy);
968
- var rad=(.08+hRad*.35)+hStr*.04;
969
- if(dd<rad){
970
- var tt=1-dd/rad,e=ss(tt)*mIn,ang=Math.atan2(dy,dx);
971
- if(hEff==='spotlight'){sc=1+e*hStr*1.8;var pf=e*e*hStr*.6;ox=Math.cos(ang)*pf*cW;oy=Math.sin(ang)*pf*cH;gl=e*hStr*.4;cb=e*e*hStr*.25}
972
- else if(hEff==='magnify'){sc=1+e*hStr*2.5;gl=e*hStr*.15}
973
- else if(hEff==='repel'){sc=1+e*hStr*.3;var pf=e*e*hStr*1.2;ox=Math.cos(ang)*pf*cW;oy=Math.sin(ang)*pf*cH}
974
- else if(hEff==='glow'){gl=e*hStr*.8;cb=e*hStr*.4}
975
- else if(hEff==='colorShift'){sc=1+e*hStr*.4;gl=e*hStr*.2;cb=e*hStr*.7}
882
+ <canvas id="${id}" width="${width}" height="${height}" style="display:block"></canvas>
883
+ <script src="https://cdn.jsdelivr.net/npm/asciify-engine@${EMBED_CDN_VERSION}/dist/embed.js"></script>
884
+ <script>Asciify('${id}',${JSON.stringify(allData)},${opts})</script>
885
+ <!-- /Asciify Animated Embed -->`;
886
+ }
887
+ function _fade(t) {
888
+ return t * t * t * (t * (t * 6 - 15) + 10);
889
+ }
890
+ function _lerp(a, b, t) {
891
+ return a + (b - a) * t;
892
+ }
893
+ function _hash2(ix, iy) {
894
+ let n = ix * 127 + iy * 311;
895
+ n = n >> 13 ^ n;
896
+ return (n * (n * n * 15731 + 789221) + 1376312589 & 2147483647) / 1073741823 - 1;
897
+ }
898
+ function _vnoise(x, y) {
899
+ const ix = Math.floor(x), iy = Math.floor(y);
900
+ const fx = x - ix, fy = y - iy;
901
+ const ux = _fade(fx), uy = _fade(fy);
902
+ const v00 = _hash2(ix, iy);
903
+ const v10 = _hash2(ix + 1, iy);
904
+ const v01 = _hash2(ix, iy + 1);
905
+ const v11 = _hash2(ix + 1, iy + 1);
906
+ return _lerp(_lerp(v00, v10, ux), _lerp(v01, v11, ux), uy);
907
+ }
908
+ function _fbm(x, y) {
909
+ return (_vnoise(x, y) * 0.5 + _vnoise(x * 2.1, y * 2.1) * 0.25 + _vnoise(x * 4.3, y * 4.3) * 0.125) / 0.875;
910
+ }
911
+ function renderWaveBackground(ctx, width, height, time, mousePos = { x: 0.5, y: 0.5 }, options = {}) {
912
+ const {
913
+ fontSize = 13,
914
+ charAspect = 0.62,
915
+ lineHeightRatio = 1.4,
916
+ chars = " .:-=+*#%@",
917
+ baseColor = null,
918
+ accentColor = "#d4ff00",
919
+ accentThreshold = 0.52,
920
+ mouseInfluence = 0.55,
921
+ mouseFalloff = 2.8,
922
+ speed = 1,
923
+ vortex = true,
924
+ sparkles = true,
925
+ breathe = true,
926
+ lightMode = false
927
+ } = options;
928
+ const charW = fontSize * charAspect;
929
+ const lineH = fontSize * lineHeightRatio;
930
+ const cols = Math.ceil(width / charW);
931
+ const rows = Math.ceil(height / lineH);
932
+ const mx = mousePos.x;
933
+ const my = mousePos.y;
934
+ let acR = 212, acG = 255, acB = 0;
935
+ if (accentColor) {
936
+ const hex = accentColor.replace("#", "");
937
+ if (hex.length === 6) {
938
+ acR = parseInt(hex.slice(0, 2), 16);
939
+ acG = parseInt(hex.slice(2, 4), 16);
940
+ acB = parseInt(hex.slice(4, 6), 16);
941
+ }
942
+ }
943
+ ctx.clearRect(0, 0, width, height);
944
+ ctx.font = `${fontSize}px "JetBrains Mono", monospace`;
945
+ ctx.textBaseline = "top";
946
+ const t = time * speed;
947
+ const breatheAmp = breathe ? (Math.sin(t * 0.22) * 0.5 + 0.5) * 0.12 : 0;
948
+ for (let row = 0; row < rows; row++) {
949
+ for (let col = 0; col < cols; col++) {
950
+ const nx = col / cols;
951
+ const ny = row / rows;
952
+ const w1 = Math.sin(col * 0.08 + row * 0.05 + t * 0.6) * 0.5 + 0.5;
953
+ const w2 = Math.sin(col * 0.03 - row * 0.07 + t * 0.4) * 0.5 + 0.5;
954
+ const w3 = Math.sin(col * 0.05 + row * 0.03 + t * 0.8) * 0.5 + 0.5;
955
+ const sinePart = (w1 + w2 + w3) / 3;
956
+ const noiseScale = 0.045;
957
+ const noiseShift = t * 0.08;
958
+ const noisePart = _fbm(col * noiseScale + noiseShift, row * noiseScale * 1.4 - noiseShift * 0.7) * 0.5 + 0.5;
959
+ const driftFreq = 0.06;
960
+ const driftPart = Math.sin((col + row * 0.65) * driftFreq + t * 1.1) * 0.5 + 0.5;
961
+ const wavePart = sinePart * 0.45 + noisePart * 0.35 + driftPart * 0.2 + breatheAmp;
962
+ const dxRaw = nx - mx;
963
+ const dyRaw = ny - my;
964
+ const distRaw = Math.sqrt(dxRaw * dxRaw + dyRaw * dyRaw);
965
+ let vortexBump = 0;
966
+ if (vortex && distRaw < 0.35) {
967
+ const angle = Math.atan2(dyRaw, dxRaw);
968
+ const swirl = Math.sin(angle * 4 + t * 2.2 - distRaw * 14);
969
+ const falloff = Math.max(0, 1 - distRaw / 0.35);
970
+ vortexBump = swirl * falloff * falloff * 0.22;
971
+ }
972
+ const proximity = Math.max(0, 1 - distRaw * mouseFalloff);
973
+ const intensity = wavePart * (1 - mouseInfluence) + (proximity + vortexBump * 0.5) * mouseInfluence + vortexBump * 0.15;
974
+ const clamped = Math.min(1, Math.max(0, intensity));
975
+ let finalIntensity = clamped;
976
+ if (sparkles && clamped > 0.72) {
977
+ const bucket = Math.floor(t * 8);
978
+ const sparkleSeed = _hash2(col * 7 + bucket * 3, row * 11 + bucket);
979
+ if (sparkleSeed > 0.88) {
980
+ finalIntensity = Math.min(1, clamped + (sparkleSeed - 0.88) * 4);
976
981
  }
977
982
  }
978
- ` : ""}
979
- var px=x*cW+cW/2+ox,py=y*cH+cH/2+oy;
980
- var col=getColor(p);
981
- if(cb>0){var m=col.match(/rgb\\((\\d+),(\\d+),(\\d+)\\)/);if(m){var rr=+m[1],gg=+m[2],bb=+m[3];col='rgb('+Math.min(255,Math.round(rr+(hcR-rr)*cb))+','+Math.min(255,Math.round(gg+(hcG-gg)*cb))+','+Math.min(255,Math.round(bb+(hcB-bb)*cb))+')'}}
982
- if(isDots){
983
- var lum=p.l/255;var int=invert?1-lum:lum;if(int<.02)continue;
984
- var rad=Math.min(cW,cH)*.5*dotR*int*sc;if(rad<.3)continue;
985
- ctx.globalAlpha=Math.min(1,(p.a/255)*(1+gl));
986
- ctx.fillStyle=col;ctx.beginPath();ctx.arc(px,py,rad,0,Math.PI*2);ctx.fill()
987
- }else{
988
- var lum=(.299*p.r+.587*p.g+.114*p.b)/255;if(invert)lum=1-lum;
989
- var ci=Math.floor(lum*(charset.length-1));
990
- var ch=charset[Math.max(0,Math.min(charset.length-1,ci))];
991
- if(ch===' ')continue;
992
- ctx.globalAlpha=Math.min(1,(p.a/255)*(1+gl));
993
- ctx.fillStyle=col;
994
- var fs=Math.min(cW/.55,cH)*.9*sc;
995
- ctx.font=fs+'px "JetBrains Mono",monospace';ctx.textAlign='center';ctx.textBaseline='middle';
996
- ctx.fillText(ch,px,py)
983
+ const charIdx = Math.floor(finalIntensity * (chars.length - 1));
984
+ if (chars[charIdx] === " ") continue;
985
+ const alpha = 0.015 + finalIntensity * 0.07;
986
+ const isAccent = finalIntensity > accentThreshold;
987
+ if (isAccent) {
988
+ const accentAlpha = Math.min(lightMode ? 0.4 : 0.28, alpha * (lightMode ? 4 : 2.8));
989
+ ctx.fillStyle = `rgba(${acR},${acG},${acB},${accentAlpha})`;
990
+ } else if (baseColor) {
991
+ ctx.fillStyle = baseColor.replace("{a}", String(alpha));
992
+ } else if (lightMode) {
993
+ ctx.fillStyle = `rgba(0,0,0,${alpha * 1.3})`;
994
+ } else {
995
+ ctx.fillStyle = `rgba(255,255,255,${alpha})`;
997
996
  }
997
+ ctx.fillText(chars[charIdx], col * charW, row * lineH);
998
998
  }
999
- ctx.globalAlpha=1;
1000
- requestAnimationFrame(draw);
1001
999
  }
1002
- requestAnimationFrame(draw);
1003
- })();
1004
- </script>
1005
- <!-- /Asciify Animated Embed -->`;
1006
1000
  }
1007
1001
 
1008
1002
  // src/webgl-engine.ts
@@ -1267,7 +1261,7 @@ function makeTexture(gl, filter = gl.NEAREST) {
1267
1261
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
1268
1262
  return t;
1269
1263
  }
1270
- var ANIM_STYLES = ["none", "wave", "pulse", "rain", "breathe", "sparkle", "glitch", "spiral", "typewriter", "scatter"];
1264
+ var ANIM_STYLES = ["none", "wave", "pulse", "rain", "breathe", "sparkle", "glitch", "spiral", "typewriter", "scatter", "waveField"];
1271
1265
  var HOVER_EFFECTS = ["spotlight", "magnify", "repel", "glow", "colorShift"];
1272
1266
  var COLOR_MODES = ["grayscale", "fullcolor", "matrix", "accent"];
1273
1267
  function tryCreateWebGLRenderer(canvas) {
@@ -1465,6 +1459,7 @@ exports.generateEmbedCode = generateEmbedCode;
1465
1459
  exports.gifToAsciiFrames = gifToAsciiFrames;
1466
1460
  exports.imageToAsciiFrame = imageToAsciiFrame;
1467
1461
  exports.renderFrameToCanvas = renderFrameToCanvas;
1462
+ exports.renderWaveBackground = renderWaveBackground;
1468
1463
  exports.tryCreateWebGLRenderer = tryCreateWebGLRenderer;
1469
1464
  exports.videoToAsciiFrames = videoToAsciiFrames;
1470
1465
  //# sourceMappingURL=index.cjs.map