asciify-engine 1.0.5 → 1.0.7

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 en(t){let f=atob(t),n=new Uint8Array(f.length);for(let s=0;s<f.length;s++)n[s]=f.charCodeAt(s);return n}function fn(t){return Array.isArray(t)?t.map(en):[en(t)]}function Mn(t,f,n,s){let e=t[0],r=1+(n*s+f)*e;if(e===4){let M=Math.round(.299*t[r]+.587*t[r+1]+.114*t[r+2]);return {r:t[r],g:t[r+1],b:t[r+2],a:t[r+3],l:M}}return {r:t[r],g:t[r],b:t[r],l:t[r],a:t[r+1]}}function gn(t){return t*t*(3-2*t)}function dn(t,f){if(t==="fullcolor")return (n,s,e)=>`rgb(${n},${s},${e})`;if(t==="matrix")return (n,s,e)=>`rgb(0,${Math.floor(.299*n+.587*s+.114*e)},0)`;if(t==="accent"){let n=f.replace("#",""),s=parseInt(n.substring(0,2),16),e=parseInt(n.substring(2,4),16),r=parseInt(n.substring(4,6),16);return (M,y,c)=>{let a=(.299*M+.587*y+.114*c)/255;return `rgb(${Math.floor(s*a)},${Math.floor(e*a)},${Math.floor(r*a)})`}}return (n,s,e)=>{let r=Math.floor(.299*n+.587*s+.114*e);return `rgb(${r},${r},${r})`}}function bn(t,f,n,s,e,r,M){let y=f,c=M*y;switch(t){case "wave":{let a=Math.sin(n/e*Math.PI*4+c*3)*.5+.5,o=Math.sin(s/r*Math.PI*3+c*2)*.5+.5;return .3+.7*(a*.6+o*.4)}case "pulse":{let a=e/2,o=r/2,u=Math.sqrt((n-a)**2+(s-o)**2),h=Math.sqrt(a*a+o*o);return .2+.8*(Math.sin(u/h*Math.PI*6-c*4)*.5+.5)}case "rain":return .1+.9*(Math.sin(s/r*Math.PI*8-c*5+n*.3)*.5+.5)*(Math.sin(n/e*Math.PI*2+c)*.3+.7);case "breathe":return Math.max(.1,Math.min(1,Math.sin(c*2)*.3+.7+Math.sin((n+s)*.1+c)*.1));case "sparkle":{let a=Math.sin(n*127.1+s*311.7+Math.floor(c*8)*43758.5453)*43758.5453,o=a-Math.floor(a);return o>.7?1:.15+o*.4}case "glitch":{let a=Math.floor(s/(r*.05)),o=Math.sin(a*43.23+Math.floor(c*6)*17.89)*43758.5453;if(o-Math.floor(o)>.85){let h=Math.sin(c*30+a)*.5+.5;return h<.3?0:h}return 1}case "spiral":{let a=e/2,o=r/2,u=n-a,h=s-o,g=Math.atan2(h,u),$=Math.sqrt(u*u+h*h),k=Math.sqrt(a*a+o*o);return .15+.85*(Math.sin(g*3+$/k*Math.PI*8-c*3)*.5+.5)}case "typewriter":{let a=e*r,o=s*e+n,u=c*.5%1,h=u*a*1.3,g=o-h;return g>0?0:Math.min(1,Math.max(0,1+g/(a*.15)))}case "scatter":{let a=e/2,o=r/2,u=n-a,h=s-o,g=Math.sqrt(u*u+h*h)/Math.sqrt(a*a+o*o),$=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 pn(t,f,n){let s=document.getElementById(t);if(!s){console.error(`Asciify: canvas #${t} not found`);return}let e=s.getContext("2d"),{r,c:M,w:y,h:c}=n,a=n.fps??10,o=n.cs??" .:-=+*#%@",u=n.cm??"grayscale",h=n.ac??"#ffffff",g=n.as??"none",$=n.sp??1,k=n.inv??false,l=n.hs??0,rn=n.hr??.3,E=n.he??"spotlight",T=n.hc??"#ffffff",sn=n.dr??.7,an=n.dots??false,K=n.anim??false,on=parseInt(T.slice(1,3),16)||255,cn=parseInt(T.slice(3,5),16)||255,hn=parseInt(T.slice(5,7),16)||255,I=y/M,w=c/r,N=fn(f),ln=dn(u,h),F=l>0,Q=g!=="none"||K,L=-1,U=-1,v=0,W=.5,X=.5,Y=0,V=0;F&&(s.addEventListener("mousemove",q=>{let P=s.getBoundingClientRect();L=(q.clientX-P.left)/P.width,U=(q.clientY-P.top)/P.height;}),s.addEventListener("mouseleave",()=>{L=-1,U=-1;}));function D(q){let P=q/1e3;K&&q-V>=1e3/a&&(Y=(Y+1)%N.length,V=q);let mn=N[Y];e.clearRect(0,0,y,c),e.fillStyle="#0a0a0a",e.fillRect(0,0,y,c),F&&(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<r;R++)for(let S=0;S<M;S++){let x=Mn(mn,S,R,M);if(x.a<10)continue;let G=bn(g,$,S,R,M,r,P);if(G<.05)continue;let C=1,J=0,j=0,B=0,A=0;if(F&&v>.003){let m=S/M,d=R/r,b=m-W,p=d-X,nn=Math.sqrt(b*b+p*p),tn=.08+rn*.35+l*.04;if(nn<tn){let un=1-nn/tn,i=gn(un)*v,O=Math.atan2(p,b);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,B=i*l*.4,A=i*i*l*.25;}else if(E==="magnify")C=1+i*l*2.5,B=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"?(B=i*l*.8,A=i*l*.4):E==="colorShift"&&(C=1+i*l*.4,B=i*l*.2,A=i*l*.7);}}let Z=S*I+I/2+J,_=R*w+w/2+j,z=ln(x.r,x.g,x.b);if(A>0){let m=z.match(/rgb\((\d+),(\d+),(\d+)\)/);if(m){let d=+m[1],b=+m[2],p=+m[3];z=`rgb(${Math.min(255,Math.round(d+(on-d)*A))},${Math.min(255,Math.round(b+(cn-b)*A))},${Math.min(255,Math.round(p+(hn-p)*A))})`;}}if(e.globalAlpha=Math.min(1,x.a/255*G*(1+B)),e.fillStyle=z,an){let m=x.l/255;if(k&&(m=1-m),m<.02)continue;let d=Math.min(I,w)*.5*sn*m*G*C;if(d<.3)continue;e.beginPath(),e.arc(Z,_,d,0,Math.PI*2),e.fill();}else {let m=x.l/255;k&&(m=1-m);let d=Math.floor(m*(o.length-1)),b=o[Math.max(0,Math.min(o.length-1,d))];if(b===" ")continue;let p=Math.min(I/.55,w)*.9*C;e.font=`${p}px "JetBrains Mono",monospace`,e.textAlign="center",e.textBaseline="middle",e.fillText(b,Z,_);}}e.globalAlpha=1,(Q||F)&&requestAnimationFrame(D);}Q||F?requestAnimationFrame(D):D(0);}window.Asciify=pn;})();
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;
@@ -699,37 +719,30 @@ function renderFrameToCanvas(ctx, frame, options, canvasWidth, canvasHeight, tim
699
719
  }
700
720
  ctx.globalAlpha = 1;
701
721
  }
702
- 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)+')'}`;
722
+ function serializeFrame(frame, fullColor) {
723
+ const rows = frame.length;
724
+ const cols = rows > 0 ? frame[0].length : 0;
725
+ const stride = fullColor ? 4 : 2;
726
+ const buf = new Uint8Array(1 + rows * cols * stride);
727
+ buf[0] = stride;
728
+ let i = 1;
729
+ for (let y = 0; y < rows; y++) {
730
+ for (let x = 0; x < cols; x++) {
731
+ const cell = frame[y][x];
732
+ if (fullColor) {
733
+ buf[i++] = cell.r;
734
+ buf[i++] = cell.g;
735
+ buf[i++] = cell.b;
736
+ buf[i++] = cell.a;
737
+ } else {
738
+ buf[i++] = Math.round(0.299 * cell.r + 0.587 * cell.g + 0.114 * cell.b);
739
+ buf[i++] = cell.a;
740
+ }
729
741
  }
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
742
  }
743
+ let binary = "";
744
+ for (let j = 0; j < buf.length; j++) binary += String.fromCharCode(buf[j]);
745
+ return btoa(binary);
733
746
  }
734
747
  async function asciify(source, canvas, { fontSize = 10, style = "classic", options = {} } = {}) {
735
748
  let el;
@@ -821,188 +834,171 @@ async function asciifyVideo(source, canvas, { fontSize = 10, style = "classic",
821
834
  cancelAnimationFrame(animId);
822
835
  };
823
836
  }
837
+ var EMBED_CDN_VERSION = "1.0.7";
838
+ function buildEmbedOpts(options, rows, cols, width, height, fps, animated) {
839
+ const o = {
840
+ r: rows,
841
+ c: cols,
842
+ w: width,
843
+ h: height,
844
+ cs: options.charset,
845
+ cm: options.colorMode,
846
+ as: options.animationStyle,
847
+ sp: options.animationSpeed,
848
+ inv: options.invert,
849
+ hs: options.hoverStrength,
850
+ hr: options.hoverRadius,
851
+ he: options.hoverEffect,
852
+ hc: options.hoverColor,
853
+ dr: options.dotSizeRatio,
854
+ dots: options.renderMode === "dots"
855
+ };
856
+ if (options.colorMode === "accent") o.ac = options.accentColor;
857
+ if (fps !== void 0) o.fps = fps;
858
+ if (animated) o.anim = true;
859
+ return JSON.stringify(o);
860
+ }
824
861
  function generateEmbedCode(frame, options, width, height) {
825
862
  const rows = frame.length;
826
863
  if (rows === 0) return "";
827
864
  const cols = frame[0].length;
828
865
  const isDots = options.renderMode === "dots";
829
866
  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));
867
+ const id = `ar-${Math.random().toString(36).slice(2, 9)}`;
868
+ const opts = buildEmbedOpts(options, rows, cols, width, height);
838
869
  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>
870
+ <canvas id="${id}" width="${width}" height="${height}" style="display:block"></canvas>
871
+ <script src="https://cdn.jsdelivr.net/npm/asciify-engine@${EMBED_CDN_VERSION}/dist/embed.js"></script>
872
+ <script>Asciify('${id}','${data}',${opts})</script>
915
873
  <!-- /Asciify Embed -->`;
916
874
  }
917
875
  function generateAnimatedEmbedCode(frames, options, fps, width, height) {
876
+ if (frames.length === 0) return "";
918
877
  const rows = frames[0].length;
919
878
  const cols = frames[0][0].length;
920
879
  const isDots = options.renderMode === "dots";
921
880
  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)));
881
+ const id = `ar-${Math.random().toString(36).slice(2, 9)}`;
882
+ const opts = buildEmbedOpts(options, rows, cols, width, height, fps, true);
929
883
  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}
884
+ <canvas id="${id}" width="${width}" height="${height}" style="display:block"></canvas>
885
+ <script src="https://cdn.jsdelivr.net/npm/asciify-engine@${EMBED_CDN_VERSION}/dist/embed.js"></script>
886
+ <script>Asciify('${id}',${JSON.stringify(allData)},${opts})</script>
887
+ <!-- /Asciify Animated Embed -->`;
888
+ }
889
+ function _fade(t) {
890
+ return t * t * t * (t * (t * 6 - 15) + 10);
891
+ }
892
+ function _lerp(a, b, t) {
893
+ return a + (b - a) * t;
894
+ }
895
+ function _hash2(ix, iy) {
896
+ let n = ix * 127 + iy * 311;
897
+ n = n >> 13 ^ n;
898
+ return (n * (n * n * 15731 + 789221) + 1376312589 & 2147483647) / 1073741823 - 1;
899
+ }
900
+ function _vnoise(x, y) {
901
+ const ix = Math.floor(x), iy = Math.floor(y);
902
+ const fx = x - ix, fy = y - iy;
903
+ const ux = _fade(fx), uy = _fade(fy);
904
+ const v00 = _hash2(ix, iy);
905
+ const v10 = _hash2(ix + 1, iy);
906
+ const v01 = _hash2(ix, iy + 1);
907
+ const v11 = _hash2(ix + 1, iy + 1);
908
+ return _lerp(_lerp(v00, v10, ux), _lerp(v01, v11, ux), uy);
909
+ }
910
+ function _fbm(x, y) {
911
+ 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;
912
+ }
913
+ function renderWaveBackground(ctx, width, height, time, mousePos = { x: 0.5, y: 0.5 }, options = {}) {
914
+ const {
915
+ fontSize = 13,
916
+ charAspect = 0.62,
917
+ lineHeightRatio = 1.4,
918
+ chars = " .:-=+*#%@",
919
+ baseColor = null,
920
+ accentColor = "#d4ff00",
921
+ accentThreshold = 0.52,
922
+ mouseInfluence = 0.55,
923
+ mouseFalloff = 2.8,
924
+ speed = 1,
925
+ vortex = true,
926
+ sparkles = true,
927
+ breathe = true,
928
+ lightMode = false
929
+ } = options;
930
+ const charW = fontSize * charAspect;
931
+ const lineH = fontSize * lineHeightRatio;
932
+ const cols = Math.ceil(width / charW);
933
+ const rows = Math.ceil(height / lineH);
934
+ const mx = mousePos.x;
935
+ const my = mousePos.y;
936
+ let acR = 212, acG = 255, acB = 0;
937
+ if (accentColor) {
938
+ const hex = accentColor.replace("#", "");
939
+ if (hex.length === 6) {
940
+ acR = parseInt(hex.slice(0, 2), 16);
941
+ acG = parseInt(hex.slice(2, 4), 16);
942
+ acB = parseInt(hex.slice(4, 6), 16);
943
+ }
944
+ }
945
+ ctx.clearRect(0, 0, width, height);
946
+ ctx.font = `${fontSize}px "JetBrains Mono", monospace`;
947
+ ctx.textBaseline = "top";
948
+ const t = time * speed;
949
+ const breatheAmp = breathe ? (Math.sin(t * 0.22) * 0.5 + 0.5) * 0.12 : 0;
950
+ for (let row = 0; row < rows; row++) {
951
+ for (let col = 0; col < cols; col++) {
952
+ const nx = col / cols;
953
+ const ny = row / rows;
954
+ const w1 = Math.sin(col * 0.08 + row * 0.05 + t * 0.6) * 0.5 + 0.5;
955
+ const w2 = Math.sin(col * 0.03 - row * 0.07 + t * 0.4) * 0.5 + 0.5;
956
+ const w3 = Math.sin(col * 0.05 + row * 0.03 + t * 0.8) * 0.5 + 0.5;
957
+ const sinePart = (w1 + w2 + w3) / 3;
958
+ const noiseScale = 0.045;
959
+ const noiseShift = t * 0.08;
960
+ const noisePart = _fbm(col * noiseScale + noiseShift, row * noiseScale * 1.4 - noiseShift * 0.7) * 0.5 + 0.5;
961
+ const driftFreq = 0.06;
962
+ const driftPart = Math.sin((col + row * 0.65) * driftFreq + t * 1.1) * 0.5 + 0.5;
963
+ const wavePart = sinePart * 0.45 + noisePart * 0.35 + driftPart * 0.2 + breatheAmp;
964
+ const dxRaw = nx - mx;
965
+ const dyRaw = ny - my;
966
+ const distRaw = Math.sqrt(dxRaw * dxRaw + dyRaw * dyRaw);
967
+ let vortexBump = 0;
968
+ if (vortex && distRaw < 0.35) {
969
+ const angle = Math.atan2(dyRaw, dxRaw);
970
+ const swirl = Math.sin(angle * 4 + t * 2.2 - distRaw * 14);
971
+ const falloff = Math.max(0, 1 - distRaw / 0.35);
972
+ vortexBump = swirl * falloff * falloff * 0.22;
973
+ }
974
+ const proximity = Math.max(0, 1 - distRaw * mouseFalloff);
975
+ const intensity = wavePart * (1 - mouseInfluence) + (proximity + vortexBump * 0.5) * mouseInfluence + vortexBump * 0.15;
976
+ const clamped = Math.min(1, Math.max(0, intensity));
977
+ let finalIntensity = clamped;
978
+ if (sparkles && clamped > 0.72) {
979
+ const bucket = Math.floor(t * 8);
980
+ const sparkleSeed = _hash2(col * 7 + bucket * 3, row * 11 + bucket);
981
+ if (sparkleSeed > 0.88) {
982
+ finalIntensity = Math.min(1, clamped + (sparkleSeed - 0.88) * 4);
976
983
  }
977
984
  }
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)
985
+ const charIdx = Math.floor(finalIntensity * (chars.length - 1));
986
+ if (chars[charIdx] === " ") continue;
987
+ const alpha = 0.015 + finalIntensity * 0.07;
988
+ const isAccent = finalIntensity > accentThreshold;
989
+ if (isAccent) {
990
+ const accentAlpha = Math.min(lightMode ? 0.4 : 0.28, alpha * (lightMode ? 4 : 2.8));
991
+ ctx.fillStyle = `rgba(${acR},${acG},${acB},${accentAlpha})`;
992
+ } else if (baseColor) {
993
+ ctx.fillStyle = baseColor.replace("{a}", String(alpha));
994
+ } else if (lightMode) {
995
+ ctx.fillStyle = `rgba(0,0,0,${alpha * 1.3})`;
996
+ } else {
997
+ ctx.fillStyle = `rgba(255,255,255,${alpha})`;
997
998
  }
999
+ ctx.fillText(chars[charIdx], col * charW, row * lineH);
998
1000
  }
999
- ctx.globalAlpha=1;
1000
- requestAnimationFrame(draw);
1001
1001
  }
1002
- requestAnimationFrame(draw);
1003
- })();
1004
- </script>
1005
- <!-- /Asciify Animated Embed -->`;
1006
1002
  }
1007
1003
 
1008
1004
  // src/webgl-engine.ts
@@ -1267,7 +1263,7 @@ function makeTexture(gl, filter = gl.NEAREST) {
1267
1263
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
1268
1264
  return t;
1269
1265
  }
1270
- var ANIM_STYLES = ["none", "wave", "pulse", "rain", "breathe", "sparkle", "glitch", "spiral", "typewriter", "scatter"];
1266
+ var ANIM_STYLES = ["none", "wave", "pulse", "rain", "breathe", "sparkle", "glitch", "spiral", "typewriter", "scatter", "waveField"];
1271
1267
  var HOVER_EFFECTS = ["spotlight", "magnify", "repel", "glow", "colorShift"];
1272
1268
  var COLOR_MODES = ["grayscale", "fullcolor", "matrix", "accent"];
1273
1269
  function tryCreateWebGLRenderer(canvas) {
@@ -1465,6 +1461,7 @@ exports.generateEmbedCode = generateEmbedCode;
1465
1461
  exports.gifToAsciiFrames = gifToAsciiFrames;
1466
1462
  exports.imageToAsciiFrame = imageToAsciiFrame;
1467
1463
  exports.renderFrameToCanvas = renderFrameToCanvas;
1464
+ exports.renderWaveBackground = renderWaveBackground;
1468
1465
  exports.tryCreateWebGLRenderer = tryCreateWebGLRenderer;
1469
1466
  exports.videoToAsciiFrames = videoToAsciiFrames;
1470
1467
  //# sourceMappingURL=index.cjs.map