litecanvas 0.86.0 → 0.88.0

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/dist.js CHANGED
@@ -31,7 +31,7 @@
31
31
  const root = window, math = Math, TWO_PI = math.PI * 2, raf = requestAnimationFrame, _browserEventListeners = [], on = (elem, evt, callback) => {
32
32
  elem.addEventListener(evt, callback, false);
33
33
  _browserEventListeners.push(() => elem.removeEventListener(evt, callback, false));
34
- }, isNumber = Number.isFinite, zzfx = setupZzFX(root), defaults = {
34
+ }, beginPath = (c) => c.beginPath(), isNumber = Number.isFinite, zzfx = setupZzFX(root), defaults = {
35
35
  width: null,
36
36
  height: null,
37
37
  autoscale: true,
@@ -246,7 +246,7 @@
246
246
  * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/roundRect
247
247
  */
248
248
  rect(x, y, width, height, color, radii) {
249
- _ctx.beginPath();
249
+ beginPath(_ctx);
250
250
  _ctx[radii ? "roundRect" : "rect"](
251
251
  ~~x - _outline_fix,
252
252
  ~~y - _outline_fix,
@@ -267,7 +267,7 @@
267
267
  * @param {number|number[]} [radii] A number or list specifying the radii used to draw a rounded-borders rectangle
268
268
  */
269
269
  rectfill(x, y, width, height, color, radii) {
270
- _ctx.beginPath();
270
+ beginPath(_ctx);
271
271
  _ctx[radii ? "roundRect" : "rect"](~~x, ~~y, ~~width, ~~height, radii);
272
272
  instance.fill(color);
273
273
  },
@@ -280,7 +280,7 @@
280
280
  * @param {number} [color=0] the color index
281
281
  */
282
282
  circ(x, y, radius, color) {
283
- _ctx.beginPath();
283
+ beginPath(_ctx);
284
284
  _ctx.arc(~~x, ~~y, ~~radius, 0, TWO_PI);
285
285
  instance.stroke(color);
286
286
  },
@@ -293,7 +293,7 @@
293
293
  * @param {number} [color=0] the color index
294
294
  */
295
295
  circfill(x, y, radius, color) {
296
- _ctx.beginPath();
296
+ beginPath(_ctx);
297
297
  _ctx.arc(~~x, ~~y, ~~radius, 0, TWO_PI);
298
298
  instance.fill(color);
299
299
  },
@@ -307,7 +307,7 @@
307
307
  * @param {number} [color=0] the color index
308
308
  */
309
309
  oval(x, y, radiusX, radiusY, color) {
310
- _ctx.beginPath();
310
+ beginPath(_ctx);
311
311
  _ctx.ellipse(~~x, ~~y, ~~radiusX, ~~radiusY, 0, 0, TWO_PI);
312
312
  instance.stroke(color);
313
313
  },
@@ -321,7 +321,7 @@
321
321
  * @param {number} [color=0] the color index
322
322
  */
323
323
  ovalfill(x, y, radiusX, radiusY, color) {
324
- _ctx.beginPath();
324
+ beginPath(_ctx);
325
325
  _ctx.ellipse(~~x, ~~y, ~~radiusX, ~~radiusY, 0, 0, TWO_PI);
326
326
  instance.fill(color);
327
327
  },
@@ -335,7 +335,7 @@
335
335
  * @param {number} [color=0] the color index
336
336
  */
337
337
  line(x1, y1, x2, y2, color) {
338
- _ctx.beginPath();
338
+ beginPath(_ctx);
339
339
  let xfix = _outline_fix !== 0 && ~~x1 === ~~x2 ? 0.5 : 0;
340
340
  let yfix = _outline_fix !== 0 && ~~y1 === ~~y2 ? 0.5 : 0;
341
341
  _ctx.moveTo(~~x1 + xfix, ~~y1 + yfix);
@@ -517,55 +517,33 @@
517
517
  _ctx.globalAlpha = instance.clamp(value, 0, 1);
518
518
  },
519
519
  /**
520
- * Returns a newly instantiated Path2D object, optionally with another
521
- * path as an argument (creates a copy), or optionally with a string
522
- * consisting of SVG path data.
523
- *
524
- * @param {Path2D|string} [arg]
525
- * @returns Path2D
526
- * @see https://developer.mozilla.org/en-US/docs/Web/API/Path2D/Path2D
527
- */
528
- path: (arg) => {
529
- return new Path2D(arg);
530
- },
531
- /**
532
- * Fills the current or given path with a given color.
520
+ * Fills the current path with a given color.
533
521
  *
534
522
  * @param {number} [color=0]
535
- * @param {Path2D} [path]
536
523
  */
537
- fill(color, path) {
524
+ fill(color) {
538
525
  _ctx.fillStyle = _colors[~~color % _colors.length];
539
- if (path) {
540
- _ctx.fill(path);
541
- } else {
542
- _ctx.fill();
543
- }
526
+ _ctx.fill();
544
527
  },
545
528
  /**
546
- * Outlines the current or given path with a given color.
529
+ * Outlines the current path with a given color.
547
530
  *
548
531
  * @param {number} [color=0]
549
- * @param {Path2D} [path]
550
532
  */
551
- stroke(color, path) {
533
+ stroke(color) {
552
534
  _ctx.strokeStyle = _colors[~~color % _colors.length];
553
- if (path) {
554
- _ctx.stroke(path);
555
- } else {
556
- _ctx.stroke();
557
- }
535
+ _ctx.stroke();
558
536
  },
559
537
  /**
560
- * Turn given path into a clipping region.
538
+ * Turns a path (in the callback) into the current clipping region.
561
539
  *
562
- * Note: always call `push()` before and `pop()` after.
563
- *
564
- * @param {Path2D} path
540
+ * @param {clipCallback} callback
565
541
  * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clip
566
542
  */
567
- clip(path) {
568
- _ctx.clip(path);
543
+ clip(callback) {
544
+ beginPath(_ctx);
545
+ callback(_ctx);
546
+ _ctx.clip();
569
547
  },
570
548
  /** SOUND API */
571
549
  /**
@@ -704,7 +682,7 @@
704
682
  // 1
705
683
  _initialized,
706
684
  // 2
707
- _rafid,
685
+ _deltaTime,
708
686
  // 3
709
687
  _scale,
710
688
  // 4
@@ -733,8 +711,7 @@
733
711
  * Stops the litecanvas instance and remove all event listeners.
734
712
  */
735
713
  quit() {
736
- cancelAnimationFrame(_rafid);
737
- _rafid = 0;
714
+ instance.pause();
738
715
  instance.emit("quit");
739
716
  _eventListeners = {};
740
717
  for (const removeListener of _browserEventListeners) {
@@ -747,6 +724,29 @@
747
724
  delete root.ENGINE;
748
725
  }
749
726
  _initialized = false;
727
+ },
728
+ /**
729
+ * Pauses the engine loop (update & draw).
730
+ */
731
+ pause() {
732
+ cancelAnimationFrame(_rafid);
733
+ _rafid = 0;
734
+ },
735
+ /**
736
+ * Resumes (if paused) the engine loop.
737
+ */
738
+ resume() {
739
+ if (!_rafid && _initialized) {
740
+ _rafid = raf(drawFrame);
741
+ }
742
+ },
743
+ /**
744
+ * Returns `true` if the engine loop is paused.
745
+ *
746
+ * @returns {boolean}
747
+ */
748
+ paused() {
749
+ return !_rafid;
750
750
  }
751
751
  };
752
752
  for (const k of _mathFunctions.split(",")) {
@@ -968,30 +968,32 @@
968
968
  }
969
969
  _initialized = true;
970
970
  instance.emit("init", instance);
971
+ instance.textalign("start", "top");
971
972
  _lastFrameTime = performance.now();
972
- _rafid = raf(drawFrame);
973
+ instance.resume();
973
974
  }
974
975
  function drawFrame(now) {
976
+ if (!settings.animate) {
977
+ return instance.emit("draw");
978
+ }
975
979
  let updated = 0;
976
- if (settings.animate) {
977
- _accumulated += math.min(0.1, (now - _lastFrameTime) / 1e3);
978
- _lastFrameTime = now;
980
+ let frameTime = (now - _lastFrameTime) / 1e3;
981
+ _lastFrameTime = now;
982
+ if (frameTime < 0.1) {
983
+ _accumulated += frameTime;
979
984
  while (_accumulated >= _deltaTime) {
980
985
  updated++;
981
986
  instance.emit("update", _deltaTime * _timeScale, updated);
982
987
  instance.def("T", instance.T + _deltaTime * _timeScale);
983
988
  _accumulated -= _deltaTime;
984
989
  }
985
- if (_rafid) {
986
- _rafid = raf(drawFrame);
987
- }
988
- } else {
989
- updated = 1;
990
990
  }
991
991
  if (updated) {
992
- instance.textalign("start", "top");
993
992
  instance.emit("draw");
994
993
  }
994
+ if (_rafid) {
995
+ _rafid = raf(drawFrame);
996
+ }
995
997
  }
996
998
  function setupCanvas() {
997
999
  if ("string" === typeof settings.canvas) {
@@ -1048,7 +1050,7 @@
1048
1050
  }
1049
1051
  if (settings.global) {
1050
1052
  if (root.ENGINE) {
1051
- throw new Error("two global litecanvas detected");
1053
+ throw new Error("only one global litecanvas is allowed");
1052
1054
  }
1053
1055
  Object.assign(root, instance);
1054
1056
  root.ENGINE = instance;
package/dist/dist.min.js CHANGED
@@ -1 +1 @@
1
- (()=>{var e=["#111","#6a7799","#aec2c2","#FFF1E8","#e83b3b","#fabc20","#155fd9","#3cbcfc","#327345","#63c64d","#6c2c1f","#ac7c00"];globalThis.litecanvas=function(t={}){let a=window,i=Math,n=2*i.PI,l=requestAnimationFrame,r=[],o=(e,t,a)=>{e.addEventListener(t,a,!1),r.push(()=>e.removeEventListener(t,a,!1))},s=(e=>{let t=new AudioContext;return e.zzfxV=1,(a=1,i=.05,n=220,l=0,r=0,o=.1,s=0,f=1,c=0,d=0,p=0,u=0,h=0,g=0,m=0,v=0,w=0,b=1,x=0,y=0,k=0)=>{let E=Math,z=2*E.PI,P=c*=500*z/44100/44100,T=n*=(1-i+2*i*E.random(i=[]))*z/44100,C=0,I=0,A=0,L=1,S=0,X=0,Y=0,M=k<0?-1:1,D=z*M*k*2/44100,N=E.cos(D),F=E.sin,q=F(D)/4,B=1+q,H=-2*N/B,O=(1-q)/B,V=(1+M*N)/2/B,W=-(M+N)/B,R=0,G=0,$=0,j=0;for(l=44100*l+9,x*=44100,r*=44100,o*=44100,w*=44100,d*=500*z/85766121e6,m*=z/44100,p*=z/44100,u*=44100,h=44100*h|0,a*=.3*e.zzfxV,M=l+x+r+o+w|0;A<M;i[A++]=Y*a)++X%(100*v|0)||(Y=s?1<s?2<s?3<s?F(C*C):E.max(E.min(E.tan(C),1),-1):1-(2*C/z%2+2)%2:1-4*E.abs(E.round(C/z)-C/z):F(C),Y=(h?1-y+y*F(z*A/h):1)*(Y<0?-1:1)*E.abs(Y)**f*(A<l?A/l:A<l+x?1-(A-l)/x*(1-b):A<l+x+r?b:A<M-w?(M-A-w)/o*b:0),Y=w?Y/2+(w>A?0:(A<M-w?1:(M-A)/w)*i[A-w|0]/2/a):Y,k&&(Y=j=V*R+W*(R=G)+V*(G=Y)-O*$-H*($=j))),C+=(D=(n+=c+=d)*E.cos(m*I++))+D*g*F(A**5),L&&++L>u&&(n+=p,T+=p,L=0),!h||++S%h||(n=T,c=P,L=L||1);(a=t.createBuffer(1,M,44100)).getChannelData(0).set(i),(n=t.createBufferSource()).buffer=a,n.connect(t.destination),n.start()}})(a);t=Object.assign({width:null,height:null,autoscale:!0,pixelart:!1,antialias:!1,canvas:null,global:!0,loop:null,tapEvents:!0,keyboardEvents:!0,animate:!0},t);let f=!1,c=[],d,p=1,u,h=.5,g=1,m,v=1/60,w=0,b,x="sans-serif",y=20,k=Date.now(),E=e,z=[.5,0,1750,,,.3,1,,,,600,.1],P={},T={W:0,H:0,T:0,MX:-1,MY:-1,TWO_PI:n,HALF_PI:n/4,lerp:(e,t,a)=>a*(t-e)+e,deg2rad:e=>i.PI/180*e,rad2deg:e=>180/i.PI*e,round:(e,t=0)=>{if(!t)return i.round(e);let a=10**t;return i.round(e*a)/a},clamp:(e,t,a)=>e<t?t:e>a?a:e,wrap:(e,t,a)=>e-(a-t)*i.floor((e-t)/(a-t)),map(e,t,a,i,n,l){let r=(e-t)/(a-t)*(n-i)+i;return l?T.clamp(r,i,n):r},norm:(e,t,a)=>T.map(e,t,a,0,1),wave:(e,t,a,i=Math.sin)=>e+(i(a)+1)/2*(t-e),rand:(e=0,t=1)=>(k=(1664525*k+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>i.floor(T.rand(e,t+1)),rseed(e){k=~~e},cls(e){null==e?u.clearRect(0,0,u.canvas.width,u.canvas.height):T.rectfill(0,0,u.canvas.width,u.canvas.height,e)},rect(e,t,a,i,n,l){u.beginPath(),u[l?"roundRect":"rect"](~~e-h,~~t-h,~~a+2*h,~~i+2*h,l),T.stroke(n)},rectfill(e,t,a,i,n,l){u.beginPath(),u[l?"roundRect":"rect"](~~e,~~t,~~a,~~i,l),T.fill(n)},circ(e,t,a,i){u.beginPath(),u.arc(~~e,~~t,~~a,0,n),T.stroke(i)},circfill(e,t,a,i){u.beginPath(),u.arc(~~e,~~t,~~a,0,n),T.fill(i)},oval(e,t,a,i,l){u.beginPath(),u.ellipse(~~e,~~t,~~a,~~i,0,0,n),T.stroke(l)},ovalfill(e,t,a,i,l){u.beginPath(),u.ellipse(~~e,~~t,~~a,~~i,0,0,n),T.fill(l)},line(e,t,a,i,n){u.beginPath();let l=.5*(0!==h&&~~e==~~a),r=.5*(0!==h&&~~t==~~i);u.moveTo(~~e+l,~~t+r),u.lineTo(~~a+l,~~i+r),T.stroke(n)},linewidth(e){u.lineWidth=~~e,h=.5*(0!=~~e%2)},linedash(e,t=0){u.setLineDash(e),u.lineDashOffset=t},text(e,t,a,i=3,n="normal"){u.font=`${n} ${y}px ${x}`,u.fillStyle=E[~~i%E.length],u.fillText(a,~~e,~~t)},textfont(e){x=e},textsize(e){y=e},textalign(e,t){e&&(u.textAlign=e),t&&(u.textBaseline=t)},image(e,t,a){u.drawImage(a,~~e,~~t)},paint(e,t,a,i={}){let n=i.canvas||new OffscreenCanvas(1,1),l=i.scale||1,r=u;if(n.width=e*l,n.height=t*l,(u=n.getContext("2d")).scale(l,l),Array.isArray(a)){let e=0,t=0;for(let i of(u.imageSmoothingEnabled=!1,a)){for(let a of i)" "!==a&&"."!==a&&T.rectfill(e,t,1,1,parseInt(a,16)),e++;t++,e=0}}else a(u);return u=r,n.transferToImageBitmap()},ctx:e=>(e&&(u=e),u),push:()=>u.save(),pop:()=>u.restore(),translate:(e,t)=>u.translate(~~e,~~t),scale:(e,t)=>u.scale(e,t||e),rotate:e=>u.rotate(e),alpha(e){u.globalAlpha=T.clamp(e,0,1)},path:e=>new Path2D(e),fill(e,t){u.fillStyle=E[~~e%E.length],t?u.fill(t):u.fill()},stroke(e,t){u.strokeStyle=E[~~e%E.length],t?u.stroke(t):u.stroke()},clip(e){u.clip(e)},sfx:(e,t=0,i=1)=>!(a.zzfxV<=0)&&(!navigator.userActivation||!!navigator.userActivation.hasBeenActive)&&(e=e||z,(0!==t||1!==i)&&((e=e.slice())[0]=i*(e[0]||1),e[10]=~~e[10]+t),s.apply(0,e),e),volume(e){a.zzfxV=e},canvas:()=>d,use(e,t={}){f?S(e,t):c.push([e,t])},listen:(e,t)=>(P[e=e.toLowerCase()]=P[e]||new Set,P[e].add(t),()=>P&&P[e].delete(t)),emit(e,t,a,i,n){f&&(L("before:"+(e=e.toLowerCase()),t,a,i,n),L(e,t,a,i,n),L("after:"+e,t,a,i,n))},pal(t=e){E=t},def(e,i){T[e]=i,t.global&&(a[e]=i)},timescale(e){g=e},framerate(e){v=1/~~e},stat(e){let i={index:e,value:[t,f,b,p,P,E,z,g,a.zzfxV||1,k,y,x][e]};return T.emit("stat",i),i.value},quit(){for(let e of(cancelAnimationFrame(b),b=0,T.emit("quit"),P={},r))e();if(t.global){for(let e in T)delete a[e];delete a.ENGINE}f=!1}};for(let e of"PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp".split(","))T[e]=i[e];function C(){let e=t.loop?t.loop:a;for(let t of"init,update,draw,tap,untap,tapping,tapped,resized".split(","))e[t]&&T.listen(t,e[t]);for(let[e,t]of c)S(e,t);if(t.autoscale&&o(a,"resize",A),t.tapEvents){let e=(e,t)=>[(e-d.offsetLeft)/p,(t-d.offsetTop)/p],t=new Map,i=(e,a,i)=>{let n={x:a,y:i,startX:a,startY:i,ts:performance.now()};return t.set(e,n),n},n=(e,a,n)=>{let l=t.get(e)||i(e);l.x=a,l.y=n},l=e=>e&&performance.now()-e.ts<=300,r=e=>e.preventDefault(),s=!1;o(d,"mousedown",t=>{if(0===t.button){r(t);let[a,n]=e(t.pageX,t.pageY);T.emit("tap",a,n,0),i(0,a,n),s=!0}}),o(d,"mouseup",a=>{if(0===a.button){r(a);let i=t.get(0),[n,o]=e(a.pageX,a.pageY);l(i)&&T.emit("tapped",i.startX,i.startY,0),T.emit("untap",n,o,0),t.delete(0),s=!1}}),o(d,"mousemove",t=>{r(t);let[a,i]=e(t.pageX,t.pageY);T.def("MX",a),T.def("MY",i),s&&(T.emit("tapping",a,i,0),n(0,a,i))}),o(d,"touchstart",t=>{for(let a of(r(t),t.changedTouches)){let[t,n]=e(a.pageX,a.pageY);T.emit("tap",t,n,a.identifier+1),i(a.identifier+1,t,n)}}),o(d,"touchmove",t=>{for(let a of(r(t),t.changedTouches)){let[t,i]=e(a.pageX,a.pageY);T.emit("tapping",t,i,a.identifier+1),n(a.identifier+1,t,i)}});let f=e=>{r(e);let a=[];if(e.targetTouches.length>0)for(let t of e.targetTouches)a.push(t.identifier+1);for(let[e,i]of t)a.includes(e)||(l(i)&&T.emit("tapped",i.startX,i.startY,e),T.emit("untap",i.x,i.y,e),t.delete(e))};o(d,"touchend",f),o(d,"touchcancel",f),o(a,"blur",()=>{for(let[e,a]of(s=!1,t))T.emit("untap",a.x,a.y,e),t.delete(e)})}if(t.keyboardEvents){let e=new Set,t=new Set,i=(e,t="")=>(t=t.toLowerCase())?e.has("space"===t?" ":t):e.size>0;o(a,"keydown",a=>{let i=a.key.toLowerCase();e.has(i)||(e.add(i),t.add(i))}),o(a,"keyup",t=>{e.delete(t.key.toLowerCase())}),o(a,"blur",()=>e.clear()),T.listen("after:update",()=>t.clear()),T.def("iskeydown",t=>i(e,t)),T.def("iskeypressed",e=>i(t,e))}f=!0,T.emit("init",T),m=performance.now(),b=l(I)}function I(e){let a=0;if(t.animate){for(w+=i.min(.1,(e-m)/1e3),m=e;w>=v;)a++,T.emit("update",v*g,a),T.def("T",T.T+v*g),w-=v;b&&(b=l(I))}else a=1;a&&(T.textalign("start","top"),T.emit("draw"))}function A(){let e=t.width||a.innerWidth,n=t.height||t.width||a.innerHeight;T.def("W",e),T.def("H",n),d.width=e,d.height=n,t.autoscale&&(d.style.display||(d.style.display="block",d.style.margin="auto"),p=i.min(a.innerWidth/e,a.innerHeight/n),p=(t.pixelart?~~p:p)||1,d.style.width=e*p+"px",d.style.height=n*p+"px"),(!t.antialias||t.pixelart)&&(u.imageSmoothingEnabled=!1,d.style.imageRendering="pixelated"),T.emit("resized",p),T.cls(0),t.animate||l(I)}function L(e,t,a,i,n){if(P[e])for(let l of P[e])l(t,a,i,n)}function S(e,t){let a=e(T,t);for(let e in a)T.def(e,a[e])}if(t.global){if(a.ENGINE)throw Error("two global litecanvas detected");Object.assign(a,T),a.ENGINE=T}return u=(d=(d="string"==typeof t.canvas?document.querySelector(t.canvas):t.canvas)||document.createElement("canvas")).getContext("2d"),o(d,"click",()=>a.focus()),d.style="",A(),d.parentNode||document.body.appendChild(d),"loading"===document.readyState?o(a,"DOMContentLoaded",()=>l(C)):l(C),T}})();
1
+ (()=>{var e=["#111","#6a7799","#aec2c2","#FFF1E8","#e83b3b","#fabc20","#155fd9","#3cbcfc","#327345","#63c64d","#6c2c1f","#ac7c00"];globalThis.litecanvas=function(t={}){let a=window,l=Math,i=2*l.PI,n=requestAnimationFrame,r=[],o=(e,t,a)=>{e.addEventListener(t,a,!1),r.push(()=>e.removeEventListener(t,a,!1))},s=e=>e.beginPath(),f=(e=>{let t=new AudioContext;return e.zzfxV=1,(a=1,l=.05,i=220,n=0,r=0,o=.1,s=0,f=1,c=0,d=0,p=0,u=0,m=0,g=0,h=0,v=0,w=0,x=1,y=0,b=0,k=0)=>{let E=Math,z=2*E.PI,T=c*=500*z/44100/44100,C=i*=(1-l+2*l*E.random(l=[]))*z/44100,I=0,A=0,L=0,S=1,X=0,Y=0,M=0,N=k<0?-1:1,P=z*N*k*2/44100,D=E.cos(P),F=E.sin,q=F(P)/4,B=1+q,H=-2*D/B,O=(1-q)/B,V=(1+N*D)/2/B,W=-(N+D)/B,R=0,G=0,$=0,j=0;for(n=44100*n+9,y*=44100,r*=44100,o*=44100,w*=44100,d*=500*z/85766121e6,h*=z/44100,p*=z/44100,u*=44100,m=44100*m|0,a*=.3*e.zzfxV,N=n+y+r+o+w|0;L<N;l[L++]=M*a)++Y%(100*v|0)||(M=s?1<s?2<s?3<s?F(I*I):E.max(E.min(E.tan(I),1),-1):1-(2*I/z%2+2)%2:1-4*E.abs(E.round(I/z)-I/z):F(I),M=(m?1-b+b*F(z*L/m):1)*(M<0?-1:1)*E.abs(M)**f*(L<n?L/n:L<n+y?1-(L-n)/y*(1-x):L<n+y+r?x:L<N-w?(N-L-w)/o*x:0),M=w?M/2+(w>L?0:(L<N-w?1:(N-L)/w)*l[L-w|0]/2/a):M,k&&(M=j=V*R+W*(R=G)+V*(G=M)-O*$-H*($=j))),I+=(P=(i+=c+=d)*E.cos(h*A++))+P*g*F(L**5),S&&++S>u&&(i+=p,C+=p,S=0),!m||++X%m||(i=C,c=T,S=S||1);(a=t.createBuffer(1,N,44100)).getChannelData(0).set(l),(i=t.createBufferSource()).buffer=a,i.connect(t.destination),i.start()}})(a);t=Object.assign({width:null,height:null,autoscale:!0,pixelart:!1,antialias:!1,canvas:null,global:!0,loop:null,tapEvents:!0,keyboardEvents:!0,animate:!0},t);let c=!1,d=[],p,u=1,m,g=.5,h=1,v,w=1/60,x=0,y,b="sans-serif",k=20,E=Date.now(),z=e,T=[.5,0,1750,,,.3,1,,,,600,.1],C={},I={W:0,H:0,T:0,MX:-1,MY:-1,TWO_PI:i,HALF_PI:i/4,lerp:(e,t,a)=>a*(t-e)+e,deg2rad:e=>l.PI/180*e,rad2deg:e=>180/l.PI*e,round:(e,t=0)=>{if(!t)return l.round(e);let a=10**t;return l.round(e*a)/a},clamp:(e,t,a)=>e<t?t:e>a?a:e,wrap:(e,t,a)=>e-(a-t)*l.floor((e-t)/(a-t)),map(e,t,a,l,i,n){let r=(e-t)/(a-t)*(i-l)+l;return n?I.clamp(r,l,i):r},norm:(e,t,a)=>I.map(e,t,a,0,1),wave:(e,t,a,l=Math.sin)=>e+(l(a)+1)/2*(t-e),rand:(e=0,t=1)=>(E=(1664525*E+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>l.floor(I.rand(e,t+1)),rseed(e){E=~~e},cls(e){null==e?m.clearRect(0,0,m.canvas.width,m.canvas.height):I.rectfill(0,0,m.canvas.width,m.canvas.height,e)},rect(e,t,a,l,i,n){s(m),m[n?"roundRect":"rect"](~~e-g,~~t-g,~~a+2*g,~~l+2*g,n),I.stroke(i)},rectfill(e,t,a,l,i,n){s(m),m[n?"roundRect":"rect"](~~e,~~t,~~a,~~l,n),I.fill(i)},circ(e,t,a,l){s(m),m.arc(~~e,~~t,~~a,0,i),I.stroke(l)},circfill(e,t,a,l){s(m),m.arc(~~e,~~t,~~a,0,i),I.fill(l)},oval(e,t,a,l,n){s(m),m.ellipse(~~e,~~t,~~a,~~l,0,0,i),I.stroke(n)},ovalfill(e,t,a,l,n){s(m),m.ellipse(~~e,~~t,~~a,~~l,0,0,i),I.fill(n)},line(e,t,a,l,i){s(m);let n=.5*(0!==g&&~~e==~~a),r=.5*(0!==g&&~~t==~~l);m.moveTo(~~e+n,~~t+r),m.lineTo(~~a+n,~~l+r),I.stroke(i)},linewidth(e){m.lineWidth=~~e,g=.5*(0!=~~e%2)},linedash(e,t=0){m.setLineDash(e),m.lineDashOffset=t},text(e,t,a,l=3,i="normal"){m.font=`${i} ${k}px ${b}`,m.fillStyle=z[~~l%z.length],m.fillText(a,~~e,~~t)},textfont(e){b=e},textsize(e){k=e},textalign(e,t){e&&(m.textAlign=e),t&&(m.textBaseline=t)},image(e,t,a){m.drawImage(a,~~e,~~t)},paint(e,t,a,l={}){let i=l.canvas||new OffscreenCanvas(1,1),n=l.scale||1,r=m;if(i.width=e*n,i.height=t*n,(m=i.getContext("2d")).scale(n,n),Array.isArray(a)){let e=0,t=0;for(let l of(m.imageSmoothingEnabled=!1,a)){for(let a of l)" "!==a&&"."!==a&&I.rectfill(e,t,1,1,parseInt(a,16)),e++;t++,e=0}}else a(m);return m=r,i.transferToImageBitmap()},ctx:e=>(e&&(m=e),m),push:()=>m.save(),pop:()=>m.restore(),translate:(e,t)=>m.translate(~~e,~~t),scale:(e,t)=>m.scale(e,t||e),rotate:e=>m.rotate(e),alpha(e){m.globalAlpha=I.clamp(e,0,1)},fill(e){m.fillStyle=z[~~e%z.length],m.fill()},stroke(e){m.strokeStyle=z[~~e%z.length],m.stroke()},clip(e){s(m),e(m),m.clip()},sfx:(e,t=0,l=1)=>!(a.zzfxV<=0)&&(!navigator.userActivation||!!navigator.userActivation.hasBeenActive)&&(e=e||T,(0!==t||1!==l)&&((e=e.slice())[0]=l*(e[0]||1),e[10]=~~e[10]+t),f.apply(0,e),e),volume(e){a.zzfxV=e},canvas:()=>p,use(e,t={}){c?Y(e,t):d.push([e,t])},listen:(e,t)=>(C[e=e.toLowerCase()]=C[e]||new Set,C[e].add(t),()=>C&&C[e].delete(t)),emit(e,t,a,l,i){c&&(X("before:"+(e=e.toLowerCase()),t,a,l,i),X(e,t,a,l,i),X("after:"+e,t,a,l,i))},pal(t=e){z=t},def(e,l){I[e]=l,t.global&&(a[e]=l)},timescale(e){h=e},framerate(e){w=1/~~e},stat(e){let l={index:e,value:[t,c,w,u,C,z,T,h,a.zzfxV||1,E,k,b][e]};return I.emit("stat",l),l.value},quit(){for(let e of(I.pause(),I.emit("quit"),C={},r))e();if(t.global){for(let e in I)delete a[e];delete a.ENGINE}c=!1},pause(){cancelAnimationFrame(y),y=0},resume(){!y&&c&&(y=n(L))},paused:()=>!y};for(let e of"PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp".split(","))I[e]=l[e];function A(){let e=t.loop?t.loop:a;for(let t of"init,update,draw,tap,untap,tapping,tapped,resized".split(","))e[t]&&I.listen(t,e[t]);for(let[e,t]of d)Y(e,t);if(t.autoscale&&o(a,"resize",S),t.tapEvents){let e=(e,t)=>[(e-p.offsetLeft)/u,(t-p.offsetTop)/u],t=new Map,l=(e,a,l)=>{let i={x:a,y:l,startX:a,startY:l,ts:performance.now()};return t.set(e,i),i},i=(e,a,i)=>{let n=t.get(e)||l(e);n.x=a,n.y=i},n=e=>e&&performance.now()-e.ts<=300,r=e=>e.preventDefault(),s=!1;o(p,"mousedown",t=>{if(0===t.button){r(t);let[a,i]=e(t.pageX,t.pageY);I.emit("tap",a,i,0),l(0,a,i),s=!0}}),o(p,"mouseup",a=>{if(0===a.button){r(a);let l=t.get(0),[i,o]=e(a.pageX,a.pageY);n(l)&&I.emit("tapped",l.startX,l.startY,0),I.emit("untap",i,o,0),t.delete(0),s=!1}}),o(p,"mousemove",t=>{r(t);let[a,l]=e(t.pageX,t.pageY);I.def("MX",a),I.def("MY",l),s&&(I.emit("tapping",a,l,0),i(0,a,l))}),o(p,"touchstart",t=>{for(let a of(r(t),t.changedTouches)){let[t,i]=e(a.pageX,a.pageY);I.emit("tap",t,i,a.identifier+1),l(a.identifier+1,t,i)}}),o(p,"touchmove",t=>{for(let a of(r(t),t.changedTouches)){let[t,l]=e(a.pageX,a.pageY);I.emit("tapping",t,l,a.identifier+1),i(a.identifier+1,t,l)}});let f=e=>{r(e);let a=[];if(e.targetTouches.length>0)for(let t of e.targetTouches)a.push(t.identifier+1);for(let[e,l]of t)a.includes(e)||(n(l)&&I.emit("tapped",l.startX,l.startY,e),I.emit("untap",l.x,l.y,e),t.delete(e))};o(p,"touchend",f),o(p,"touchcancel",f),o(a,"blur",()=>{for(let[e,a]of(s=!1,t))I.emit("untap",a.x,a.y,e),t.delete(e)})}if(t.keyboardEvents){let e=new Set,t=new Set,l=(e,t="")=>(t=t.toLowerCase())?e.has("space"===t?" ":t):e.size>0;o(a,"keydown",a=>{let l=a.key.toLowerCase();e.has(l)||(e.add(l),t.add(l))}),o(a,"keyup",t=>{e.delete(t.key.toLowerCase())}),o(a,"blur",()=>e.clear()),I.listen("after:update",()=>t.clear()),I.def("iskeydown",t=>l(e,t)),I.def("iskeypressed",e=>l(t,e))}c=!0,I.emit("init",I),I.textalign("start","top"),v=performance.now(),I.resume()}function L(e){if(!t.animate)return I.emit("draw");let a=0,l=(e-v)/1e3;if(v=e,l<.1)for(x+=l;x>=w;)a++,I.emit("update",w*h,a),I.def("T",I.T+w*h),x-=w;a&&I.emit("draw"),y&&(y=n(L))}function S(){let e=t.width||a.innerWidth,i=t.height||t.width||a.innerHeight;I.def("W",e),I.def("H",i),p.width=e,p.height=i,t.autoscale&&(p.style.display||(p.style.display="block",p.style.margin="auto"),u=l.min(a.innerWidth/e,a.innerHeight/i),u=(t.pixelart?~~u:u)||1,p.style.width=e*u+"px",p.style.height=i*u+"px"),(!t.antialias||t.pixelart)&&(m.imageSmoothingEnabled=!1,p.style.imageRendering="pixelated"),I.emit("resized",u),I.cls(0),t.animate||n(L)}function X(e,t,a,l,i){if(C[e])for(let n of C[e])n(t,a,l,i)}function Y(e,t){let a=e(I,t);for(let e in a)I.def(e,a[e])}if(t.global){if(a.ENGINE)throw Error("only one global litecanvas is allowed");Object.assign(a,I),a.ENGINE=I}return m=(p=(p="string"==typeof t.canvas?document.querySelector(t.canvas):t.canvas)||document.createElement("canvas")).getContext("2d"),o(p,"click",()=>a.focus()),p.style="",S(),p.parentNode||document.body.appendChild(p),"loading"===document.readyState?o(a,"DOMContentLoaded",()=>n(A)):n(A),I}})();
package/package.json CHANGED
@@ -1,21 +1,10 @@
1
1
  {
2
2
  "name": "litecanvas",
3
- "version": "0.86.0",
3
+ "version": "0.88.0",
4
4
  "description": "Lightweight HTML5 canvas 2D game engine suitable for small projects and creative coding. Inspired by PICO-8 and P5/Processing.",
5
5
  "license": "MIT",
6
6
  "author": "Luiz Bills <luizbills@pm.me>",
7
7
  "contributors": [],
8
- "devDependencies": {
9
- "@litecanvas/jsdom-extras": "^1.1.0",
10
- "@swc/core": "^1.12.7",
11
- "@types/jsdom": "^21.1.7",
12
- "ava": "^6.4.0",
13
- "esbuild": "^0.25.5",
14
- "gzip-size": "^7.0.0",
15
- "jsdom": "^26.1.0",
16
- "prettier": "^3.6.2",
17
- "tap-min": "^3.0.0"
18
- },
19
8
  "homepage": "https://litecanvas.github.io/about.html",
20
9
  "repository": {
21
10
  "type": "git",
@@ -27,17 +16,6 @@
27
16
  "type": "module",
28
17
  "main": "src/index.js",
29
18
  "types": "types/index.d.ts",
30
- "scripts": {
31
- "test": "ava --tap | tap-min",
32
- "test:watch": "ava --watch",
33
- "dev": "esbuild src/web.js --bundle --watch --outfile=dist/dist.dev.js --servedir=.",
34
- "build": "node script/build.js",
35
- "gzip-size": "gzip -c dist/dist.min.js | wc -c | xargs printf \" Gzip size: %s bytes\n\"",
36
- "format": "prettier -w src/* samples/* types/* script/* types/*",
37
- "check-types": "npx ts types/*",
38
- "prepare": "npm run build",
39
- "prepublishOnly": "npm test"
40
- },
41
19
  "keywords": [
42
20
  "canvas",
43
21
  "2d",
@@ -50,6 +28,36 @@
50
28
  "pico-8",
51
29
  "p5"
52
30
  ],
31
+ "devDependencies": {
32
+ "@litecanvas/jsdom-extras": "^2.0.0",
33
+ "@size-limit/preset-small-lib": "^11.2.0",
34
+ "@swc/core": "^1.12.9",
35
+ "@types/jsdom": "^21.1.7",
36
+ "ava": "^6.4.0",
37
+ "esbuild": "^0.25.5",
38
+ "genversion": "^3.2.0",
39
+ "gzip-size": "^7.0.0",
40
+ "jsdom": "^26.1.0",
41
+ "prettier": "^3.6.2",
42
+ "sinon": "^21.0.0",
43
+ "size-limit": "^11.2.0",
44
+ "tap-min": "^3.0.0"
45
+ },
46
+ "trustedDependencies": [
47
+ "@swc/core"
48
+ ],
49
+ "scripts": {
50
+ "prepare": "npm run build",
51
+ "prepublishOnly": "npm test",
52
+ "test": "ava --timeout=1s --fast-fail --tap | tap-min",
53
+ "test:watch": "ava --watch",
54
+ "dev": "esbuild src/web.js --bundle --watch --outfile=dist/dist.dev.js --servedir=.",
55
+ "build": "npm run genversion && node script/build.js && size-limit",
56
+ "gzip-size": "gzip -c dist/dist.min.js | wc -c | xargs printf \" Gzip size: %s bytes\n\"",
57
+ "format": "prettier -w src/* samples/* types/* script/* types/*",
58
+ "check-types": "npx ts types/*",
59
+ "genversion": "genversion --es6 --semi version.js"
60
+ },
53
61
  "files": [
54
62
  "dist",
55
63
  "src",
@@ -60,7 +68,16 @@
60
68
  "tests/**/*.js"
61
69
  ]
62
70
  },
63
- "trustedDependencies": [
64
- "@swc/core"
71
+ "size-limit": [
72
+ {
73
+ "path": "dist/dist.min.js",
74
+ "limit": "4kb",
75
+ "gzip": true
76
+ },
77
+ {
78
+ "path": "dist/dist.min.js",
79
+ "limit": "4kb",
80
+ "gzip": false
81
+ }
65
82
  ]
66
83
  }