litecanvas 0.302.0 → 0.400.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/README.md CHANGED
@@ -100,15 +100,28 @@ Litecanvas has a default palette with 4 colors:
100
100
 
101
101
  <img src=".github/_assets/palette.png" src="The litecanvas color palette" style="2px solid #fff">
102
102
 
103
- Each time a Litecanvas' function ask for a color, you should use an of theses colors by its index.
103
+ Each time a Litecanvas' function ask for a color, you can use an of theses colors by its index (from 0 to 3, by default). But, you can customize the color palette using the `pal()` function. [Example](samples/custom-palette/custom-palette.js)
104
104
 
105
105
  ```js
106
- // example: draw a white rectangle
106
+ litecanvas()
107
+
108
+ // example: draw a white (color #3) rectangle
107
109
  let color = 3
108
110
  rectfill(0, 0, 32, 32, color)
109
111
  ```
110
112
 
111
- > Note: You can customize the color palette using the `pal()` function. [Example](samples/custom-palette/custom-palette.js)
113
+ However, you can also use any other color:
114
+
115
+ ```js
116
+ litecanvas()
117
+
118
+ // example: draw three "orange" rectangles
119
+ rectfill(0, 0, 32, 32, 'orange')
120
+ rectfill(32, 32, 32, 32, '#ffa500')
121
+ rectfill(64, 64, 32, 32, 'rgb(255, 165, 0)')
122
+ ```
123
+
124
+ [Live Demo](https://litecanvas.js.org?c=eJxNytEKgzAMBdD3fkVwD22hYKerD%2Fub6FIVMjdimX6%2BFZkb5IYL9%2FCYqMPpg7OxSpUl0IrPN9MdHoILpEGIoHgJTj0VINSl3Jhmtdc4MhvvIF9dHdEH1fYHvtNJLjFi8P7fNDcHe04jfWuqEBxcm%2Fy81XYDYQwvNQ%3D%3D)
112
125
 
113
126
  ### Printing messages
114
127
 
@@ -120,9 +133,10 @@ function draw() {
120
133
  cls(0)
121
134
 
122
135
  // print a gray (color #1) text at x=0, y=0
123
- text(0, 0, 'Hello!!!', 1)
136
+ const color = 1
137
+ text(0, 0, 'Hello!!!', color)
124
138
 
125
- // use \n to break text lines
139
+ // use \n to break text lines (by default uses the color #3)
126
140
  text(0, 30, 'multi\nline\ntext')
127
141
  }
128
142
  ```
package/dist/dist.dev.js CHANGED
@@ -115,7 +115,7 @@
115
115
  var assert = (condition, message = "Assertion failed") => {
116
116
  if (!condition) throw new Error("[Litecanvas] " + message);
117
117
  };
118
- var version = "0.302.0";
118
+ var version = "0.400.0";
119
119
  function litecanvas(settings = {}) {
120
120
  const root = window,
121
121
  math = Math,
@@ -296,8 +296,10 @@
296
296
  },
297
297
  cls(color) {
298
298
  DEV: assert(
299
- null == color || (isNumber(color) && color >= 0),
300
- "cls() 1st argument must be a non-negative number",
299
+ null == color ||
300
+ (isNumber(color) && color >= 0) ||
301
+ "string" === typeof color,
302
+ "cls() 1st argument must be a non-negative number or string",
301
303
  );
302
304
  if (null == color) {
303
305
  _ctx.clearRect(0, 0, instance.W, instance.H);
@@ -317,8 +319,10 @@
317
319
  "rect() 4th argument must be a non-negative number",
318
320
  );
319
321
  DEV: assert(
320
- null == color || (isNumber(color) && color >= 0),
321
- "rect() 5th argument must be a non-negative number",
322
+ null == color ||
323
+ (isNumber(color) && color >= 0) ||
324
+ "string" === typeof color,
325
+ "rect() 5th argument must be a non-negative number or string",
322
326
  );
323
327
  DEV: assert(
324
328
  null == radii ||
@@ -348,8 +352,10 @@
348
352
  "rectfill() 4th argument must be a non-negative number",
349
353
  );
350
354
  DEV: assert(
351
- null == color || (isNumber(color) && color >= 0),
352
- "rectfill() 5th argument must be a non-negative number",
355
+ null == color ||
356
+ (isNumber(color) && color >= 0) ||
357
+ "string" === typeof color,
358
+ "rectfill() 5th argument must be a non-negative number or string",
353
359
  );
354
360
  DEV: assert(
355
361
  null == radii ||
@@ -373,8 +379,10 @@
373
379
  "oval() 4th argument must be a non-negative number",
374
380
  );
375
381
  DEV: assert(
376
- null == color || (isNumber(color) && color >= 0),
377
- "oval() 5th argument must be a non-negative number",
382
+ null == color ||
383
+ (isNumber(color) && color >= 0) ||
384
+ "string" === typeof color,
385
+ "oval() 5th argument must be a non-negative number or string",
378
386
  );
379
387
  beginPath(_ctx);
380
388
  _ctx.ellipse(~~x, ~~y, ~~radiusX, ~~radiusY, 0, 0, TAU);
@@ -392,8 +400,10 @@
392
400
  "ovalfill() 4th argument must be a non-negative number",
393
401
  );
394
402
  DEV: assert(
395
- null == color || (isNumber(color) && color >= 0),
396
- "ovalfill() 5th argument must be a non-negative number",
403
+ null == color ||
404
+ (isNumber(color) && color >= 0) ||
405
+ "string" === typeof color,
406
+ "ovalfill() 5th argument must be a non-negative number or string",
397
407
  );
398
408
  beginPath(_ctx);
399
409
  _ctx.ellipse(~~x, ~~y, ~~radiusX, ~~radiusY, 0, 0, TAU);
@@ -407,8 +417,10 @@
407
417
  "circ() 3rd argument must be a non-negative number",
408
418
  );
409
419
  DEV: assert(
410
- null == color || (isNumber(color) && color >= 0),
411
- "circ() 4th argument must be a non-negative number",
420
+ null == color ||
421
+ (isNumber(color) && color >= 0) ||
422
+ "string" === typeof color,
423
+ "circ() 4th argument must be a non-negative number or string",
412
424
  );
413
425
  instance.oval(x, y, radius, radius, color);
414
426
  },
@@ -420,8 +432,10 @@
420
432
  "circfill() 3rd argument must be a non-negative number",
421
433
  );
422
434
  DEV: assert(
423
- null == color || (isNumber(color) && color >= 0),
424
- "circfill() 4th argument must be a non-negative number",
435
+ null == color ||
436
+ (isNumber(color) && color >= 0) ||
437
+ "string" === typeof color,
438
+ "circfill() 4th argument must be a non-negative number or string",
425
439
  );
426
440
  instance.ovalfill(x, y, radius, radius, color);
427
441
  },
@@ -456,8 +470,10 @@
456
470
  "line() 4th argument must be a non-negative number",
457
471
  );
458
472
  DEV: assert(
459
- null == color || (isNumber(color) && color >= 0),
460
- "line() 5th argument must be a non-negative number",
473
+ null == color ||
474
+ (isNumber(color) && color >= 0) ||
475
+ "string" === typeof color,
476
+ "line() 5th argument must be a non-negative number or string",
461
477
  );
462
478
  beginPath(_ctx);
463
479
  let xfix = _outline_fix && ~~x1 === ~~x2 ? 0.5 : 0;
@@ -490,8 +506,10 @@
490
506
  DEV: assert(isNumber(x), "text() 1st argument must be a number");
491
507
  DEV: assert(isNumber(y), "text() 2nd argument must be a number");
492
508
  DEV: assert(
493
- null == color || (isNumber(color) && color >= 0),
494
- "text() 4th argument must be a non-negative number",
509
+ null == color ||
510
+ (isNumber(color) && color >= 0) ||
511
+ "string" === typeof color,
512
+ "text() 4th argument must be a non-negative number or string",
495
513
  );
496
514
  DEV: assert(
497
515
  "string" === typeof fontStyle,
@@ -669,16 +687,20 @@
669
687
  },
670
688
  fill(color) {
671
689
  DEV: assert(
672
- null == color || (isNumber(color) && color >= 0),
673
- "fill() 1st argument must be a non-negative number",
690
+ null == color ||
691
+ (isNumber(color) && color >= 0) ||
692
+ "string" === typeof color,
693
+ "fill() 1st argument must be a non-negative number or string",
674
694
  );
675
695
  _ctx.fillStyle = getColor(color);
676
696
  _ctx.fill();
677
697
  },
678
698
  stroke(color) {
679
699
  DEV: assert(
680
- null == color || (isNumber(color) && color >= 0),
681
- "stroke() 1st argument must be a non-negative number",
700
+ null == color ||
701
+ (isNumber(color) && color >= 0) ||
702
+ "string" === typeof color,
703
+ "stroke() 1st argument must be a non-negative number or string",
682
704
  );
683
705
  _ctx.strokeStyle = getColor(color);
684
706
  _ctx.stroke();
@@ -935,7 +957,7 @@
935
957
  },
936
958
  };
937
959
  const mathProps =
938
- "PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp";
960
+ "PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,min,max,pow,sqrt,sign";
939
961
  for (const k of mathProps.split(",")) {
940
962
  instance[k] = math[k];
941
963
  }
@@ -1192,9 +1214,12 @@
1192
1214
  instance.def(key, pluginData[key]);
1193
1215
  }
1194
1216
  }
1195
- function getColor(index) {
1196
- const i = _colorPaletteState[index] ?? index;
1197
- return _currentPalette[~~i % _currentPalette.length];
1217
+ function getColor(color) {
1218
+ return color >= 0
1219
+ ? _currentPalette[
1220
+ ~~(_colorPaletteState[color] ?? color) % _currentPalette.length
1221
+ ]
1222
+ : color;
1198
1223
  }
1199
1224
  if (settings.global) {
1200
1225
  if (root.ENGINE) {
package/dist/dist.js CHANGED
@@ -531,7 +531,7 @@
531
531
  },
532
532
  };
533
533
  const mathProps =
534
- "PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp";
534
+ "PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,min,max,pow,sqrt,sign";
535
535
  for (const k of mathProps.split(",")) {
536
536
  instance[k] = math[k];
537
537
  }
@@ -749,9 +749,12 @@
749
749
  instance.def(key, pluginData[key]);
750
750
  }
751
751
  }
752
- function getColor(index) {
753
- const i = _colorPaletteState[index] ?? index;
754
- return _currentPalette[~~i % _currentPalette.length];
752
+ function getColor(color) {
753
+ return color >= 0
754
+ ? _currentPalette[
755
+ ~~(_colorPaletteState[color] ?? color) % _currentPalette.length
756
+ ]
757
+ : color;
755
758
  }
756
759
  if (settings.global) {
757
760
  if (root.ENGINE) {
package/dist/dist.min.js CHANGED
@@ -1 +1 @@
1
- (()=>{var e=["#211e20","#555568","#a0a08b","#e9efec"];window.litecanvas=function(t={}){let a,l=window,n=Math,i=performance,o=2*n.PI,r=requestAnimationFrame,s=[],f=(e,t,a)=>{e.addEventListener(t,a,!1),s.push(()=>e.removeEventListener(t,a,!1))},c=(l.zzfxX=new AudioContext,l.zzfxV=1,(e=1,t=.05,a=220,l=0,n=0,i=.1,o=0,r=1,s=0,f=0,c=0,d=0,u=0,p=0,h=0,m=0,g=0,w=1,v=0,x=0,y=0)=>{let b=Math,z=2*b.PI,k=s*=500*z/44100/44100,E=a*=(1-t+2*t*b.random(t=[]))*z/44100,T=0,C=0,P=0,I=1,D=0,L=0,S=0,A=y<0?-1:1,M=z*A*y*2/44100,N=b.cos(M),W=b.sin,X=W(M)/4,H=1+X,q=-2*N/H,B=(1-X)/H,V=(1+A*N)/2/H,O=-(A+N)/H,G=0,R=0,Y=0,$=0;for(l=44100*l+9,v*=44100,n*=44100,i*=44100,g*=44100,f*=500*z/85766121e6,h*=z/44100,c*=z/44100,d*=44100,u=44100*u|0,e*=.3*zzfxV,A=l+v+n+i+g|0;P<A;t[P++]=S*e)++L%(100*m|0)||(S=o?1<o?2<o?3<o?W(T*T):b.max(b.min(b.tan(T),1),-1):1-(2*T/z%2+2)%2:1-4*b.abs(b.round(T/z)-T/z):W(T),S=(u?1-x+x*W(z*P/u):1)*(S<0?-1:1)*b.abs(S)**r*(P<l?P/l:P<l+v?1-(P-l)/v*(1-w):P<l+v+n?w:P<A-g?(A-P-g)/i*w:0),S=g?S/2+(g>P?0:(P<A-g?1:(A-P)/g)*t[P-g|0]/2/e):S,y&&(S=$=V*G+O*(G=R)+V*(R=S)-B*Y-q*(Y=$))),T+=(M=(a+=s+=f)*b.cos(h*C++))+M*p*W(P**5),I&&++I>d&&(a+=c,E+=c,I=0),!u||++D%u||(a=E,s=k,I=I||1);(e=zzfxX.createBuffer(1,A,44100)).getChannelData(0).set(t),(a=zzfxX.createBufferSource()).buffer=e,a.connect(zzfxX.destination),a.start()}),d=(t=Object.assign({width:null,height:null,autoscale:!0,canvas:null,global:!0,loop:null,tapEvents:!0,keyboardEvents:!0},t)).loop,u,p,h,m=1,g,w=.5,v=1,x,y=1e3/60,b,z=0,k=3,E="sans-serif",T=20,C=1.2,P=Date.now(),I=e,D=e,L=[],S=[.5,0,1750,,,.3,1,,,,600,.1],A={},M={W:0,H:0,T:0,MX:-1,MY:-1,TAU:o,lerp:(e,t,a)=>e+a*(t-e),deg2rad:e=>n.PI/180*e,rad2deg:e=>180/n.PI*e,mod:(e,t)=>(e%t+t)%t||0,round:(e,t=0)=>{if(!t)return n.round(e);let a=10**t;return n.round(e*a)/a},clamp:(e,t,a)=>e<t?t:e>a?a:e,dist:(e,t,a,l)=>n.hypot(a-e,l-t),wrap:(e,t,a)=>e-(a-t)*n.floor((e-t)/(a-t)),map(e,t,a,l,n,i){let o=(e-t)/(a-t)*(n-l)+l;return i?M.clamp(o,l,n):o},norm:(e,t,a)=>M.map(e,t,a,0,1),rand:(e=0,t=1)=>(P=(1664525*P+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>~~M.rand(e,t+1),rseed(e){P=~~e},cls(e){null==e?g.clearRect(0,0,M.W,M.H):M.rectfill(0,0,M.W,M.H,e)},rect(e,t,a,l,n,i){g.beginPath(),g[i?"roundRect":"rect"](~~e-w,~~t-w,~~a+2*w,~~l+2*w,i),M.stroke(n)},rectfill(e,t,a,l,n,i){g.beginPath(),g[i?"roundRect":"rect"](~~e,~~t,~~a,~~l,i),M.fill(n)},oval(e,t,a,l,n){g.beginPath(),g.ellipse(~~e,~~t,~~a,~~l,0,0,o),M.stroke(n)},ovalfill(e,t,a,l,n){g.beginPath(),g.ellipse(~~e,~~t,~~a,~~l,0,0,o),M.fill(n)},circ(e,t,a,l){M.oval(e,t,a,a,l)},circfill(e,t,a,l){M.ovalfill(e,t,a,a,l)},shape(e){g.beginPath();for(let t=0;t<e.length;t+=2)t?g.lineTo(~~e[t],~~e[t+1]):g.moveTo(~~e[t],~~e[t+1]);g.lineTo(~~e[0],~~e[1])},line(e,t,a,l,n){g.beginPath();let i=w&&~~e==~~a?.5:0,o=w&&~~t==~~l?.5:0;g.moveTo(~~e+i,~~t+o),g.lineTo(~~a+i,~~l+o),M.stroke(n)},linewidth(e){g.lineWidth=~~e,w=~~e%2?.5:0},linedash(e,t=0){g.setLineDash(e),g.lineDashOffset=t},text(e,t,a,l=k,n="normal"){g.font=`${n} ${T}px ${E}`,g.fillStyle=q(l);let i=(""+a).split("\n");for(let a=0;a<i.length;a++)g.fillText(i[a],~~e,~~t+T*C*a)},textgap(e){C=e},textfont(e){E=e},textsize(e){T=e},textalign(e,t){e&&(g.textAlign=e),t&&(g.textBaseline=t)},image(e,t,a){g.drawImage(a,~~e,~~t)},spr(e,t,a){let l=a.replace(/[^\w.\n]/g,"").split("\n").filter(e=>e);for(let a=0;a<l.length;a++)for(let n=0;n<l[a].length;n++)"."!==l[a][n]&&M.rectfill(e+n,t+a,1,1,parseInt(l[a][n],36)||0)},paint(e,t,a,l={}){let n=l.canvas||new OffscreenCanvas(1,1),i=l.scale||1,o=g;return n.width=e*i,n.height=t*i,(g=n.getContext("2d")).scale(i,i),a(g),g=o,n.transferToImageBitmap()},ctx:e=>(e&&(g=e),g),push(e=0,t=e,a=0,l=1,n=l){g.save(),M.translate(e,t),M.rotate(a),M.scale(l,n)},pop(){g.restore()},translate(e,t){g.translate(~~e,~~t)},scale(e,t=e){g.scale(e,t)},rotate(e){g.rotate(e)},alpha(e){g.globalAlpha=M.clamp(e,0,1)},fill(e){g.fillStyle=q(e),g.fill()},stroke(e){g.strokeStyle=q(e),g.stroke()},clip(e){g.beginPath(),e(g),g.clip()},sfx:(e,t,a)=>!!l.zzfxV&&(!navigator.userActivation||!!navigator.userActivation.hasBeenActive)&&(e||=S,(t||a>=0)&&((e=e.slice())[0]=a*(e[0]||1),e[10]=~~e[10]+t),c.apply(0,e),e),volume(e){l.zzfxV=e},canvas:()=>h,use(e,t={}){var a=e,l=t;let n=a(M,l);for(let e in n)M.def(e,n[e])},resize(e,a=e,l){t.width=e,t.height=a,t.autoscale=null==l?t.autoscale:l,X()},listen:(e,t)=>{A[e=e.toLowerCase()]=A[e]||new Set,A[e].add(t)},unlisten:(e,t)=>{A[e=e.toLowerCase()]&&A[e].delete(t)},emit:(e,t,a,n,i)=>(u&&(H("before:"+(e=e.toLowerCase()),t,a,n,i),d||l[e]===M[e]||"function"!=typeof l[e]||l[e](t,a,n,i),H(e,t,a,n,i),H("after:"+e,t,a,n,i)),t),pal(e,t=3){null==e?I=D:(D=I,I=e),L=[],k=t,M.emit("pal",I,k)},palc(e,t){null==e?L=[]:L[e]=t},def(e,a){M[e]=a,t.global&&(l[e]=a)},timescale(e){v=e},framerate(e){y=1e3/~~e},stat:e=>[t,u,y/1e3,m,A,I,S,v,l.zzfxV,P,T,E,L,C][e],ispaused:()=>p,pause(){p||(p=!0,z=~~cancelAnimationFrame(z),M.emit("paused"))},resume(){u&&p&&(N(),p=!1,M.emit("resumed"))},quit(){for(let e of(M.emit("quit"),M.pause(),u=!1,A={},s))e();if(t.global){for(let e in M)delete l[e];delete l.ENGINE}}};for(let e of"PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp".split(","))M[e]=n[e];function N(){z||(b=0,x=i.now(),z=r(W))}function W(){z=r(W);let e=i.now(),t=0,a=e-x;for(x=e,b+=a<100?a:y;b>=y;){t++,b-=y;let e=y/1e3*v;M.emit("update",e,t),M.def("T",M.T+e)}t&&(M.emit("draw",g),t>1&&(b=0))}function X(){let e=t.width>0?t.width:innerWidth,a=t.width>0?t.height||t.width:innerHeight;if(M.def("W",e),M.def("H",a),h.width=e,h.height=a,h.style="image-rendering:pixelated",t.autoscale){let l=+t.autoscale;h.style.display||(h.style.display="block",h.style.margin="auto"),m=n.min(innerWidth/e,innerHeight/a),m=l>1&&m>l?l:m,h.style.width=e*m+"px",h.style.height=a*m+"px"}g.imageSmoothingEnabled=!1,M.textalign("start","top"),M.emit("resized",m)}function H(e,t,a,l,n){if(A[e])for(let i of A[e])i(t,a,l,n)}function q(e){return I[~~(L[e]??e)%I.length]}if(t.global){if(l.ENGINE)throw Error("only one global litecanvas is allowed");Object.assign(l,M),l.ENGINE=M}if(a=document,g=(h=(h="string"==typeof t.canvas?a.querySelector(t.canvas):t.canvas)||a.createElement("canvas")).getContext("2d"),f(h,"click",()=>focus()),h.parentNode||a.body.appendChild(h),h.oncontextmenu=()=>!1,X(),d)for(let e in d)d[e]&&M.listen(e,d[e]);return r(function(){if(t.autoscale&&f(l,"resize",X),t.tapEvents){let e=e=>[(e.pageX-h.offsetLeft)/m,(e.pageY-h.offsetTop)/m],t=new Map,a=(e,a,l)=>{let n={x:a,y:l,xi:a,yi:l,t:i.now()};return t.set(e,n),n},n=(e,l,n)=>{let i=t.get(e)||a(e);i.x=l,i.y=n},o=e=>e&&i.now()-e.t<=300,r=!1;f(h,"mousedown",t=>{if(!t.button){t.preventDefault();let[l,n]=e(t);M.emit("tap",l,n,0),a(0,l,n),r=!0}}),f(h,"mouseup",a=>{if(!a.button){a.preventDefault();let l=t.get(0),[n,i]=e(a);o(l)&&M.emit("tapped",l.xi,l.yi,0),M.emit("untap",n,i,0),t.delete(0),r=!1}}),f(l,"mousemove",t=>{t.preventDefault();let[a,l]=e(t);M.def("MX",a),M.def("MY",l),r&&(M.emit("tapping",a,l,0),n(0,a,l))}),f(h,"touchstart",t=>{for(let l of(t.preventDefault(),t.changedTouches)){let[t,n]=e(l);M.emit("tap",t,n,l.identifier+1),a(l.identifier+1,t,n)}}),f(h,"touchmove",t=>{for(let a of(t.preventDefault(),t.changedTouches)){let[t,l]=e(a);M.emit("tapping",t,l,a.identifier+1),n(a.identifier+1,t,l)}});let s=e=>{e.preventDefault();let a=[];for(let t of e.targetTouches)a.push(t.identifier+1);for(let[e,l]of t)a.includes(e)||(o(l)&&M.emit("tapped",l.xi,l.yi,e),M.emit("untap",l.x,l.y,e),t.delete(e))};f(h,"touchend",s),f(h,"touchcancel",s),f(l,"blur",()=>{for(let[e,a]of(r=!1,t))M.emit("untap",a.x,a.y,e),t.delete(e)})}if(t.keyboardEvents){let e=new Set,t=new Set,a=(e,t="")=>(t=t.toLowerCase())?e.has("space"===t?" ":t):e.size>0,n="";f(l,"keydown",a=>{let l=a.key.toLowerCase();e.has(l)||(e.add(l),t.add(l),n=" "===l?"space":l)}),f(l,"keyup",t=>{e.delete(t.key.toLowerCase())}),f(l,"blur",()=>e.clear()),M.listen("after:update",()=>t.clear()),M.def("iskeydown",t=>a(e,t)),M.def("iskeypressed",e=>a(t,e)),M.def("lastkey",()=>n)}u=!0,M.emit("init",M),p||N()}),M}})();
1
+ (()=>{var e=["#211e20","#555568","#a0a08b","#e9efec"];window.litecanvas=function(t={}){let a,l=window,n=Math,i=performance,o=2*n.PI,r=requestAnimationFrame,s=[],f=(e,t,a)=>{e.addEventListener(t,a,!1),s.push(()=>e.removeEventListener(t,a,!1))},d=(l.zzfxX=new AudioContext,l.zzfxV=1,(e=1,t=.05,a=220,l=0,n=0,i=.1,o=0,r=1,s=0,f=0,d=0,c=0,u=0,p=0,h=0,m=0,g=0,w=1,v=0,x=0,y=0)=>{let b=Math,z=2*b.PI,k=s*=500*z/44100/44100,E=a*=(1-t+2*t*b.random(t=[]))*z/44100,T=0,C=0,P=0,I=1,D=0,L=0,S=0,A=y<0?-1:1,M=z*A*y*2/44100,N=b.cos(M),W=b.sin,X=W(M)/4,H=1+X,q=-2*N/H,B=(1-X)/H,V=(1+A*N)/2/H,O=-(A+N)/H,G=0,R=0,Y=0,$=0;for(l=44100*l+9,v*=44100,n*=44100,i*=44100,g*=44100,f*=500*z/85766121e6,h*=z/44100,d*=z/44100,c*=44100,u=44100*u|0,e*=.3*zzfxV,A=l+v+n+i+g|0;P<A;t[P++]=S*e)++L%(100*m|0)||(S=o?1<o?2<o?3<o?W(T*T):b.max(b.min(b.tan(T),1),-1):1-(2*T/z%2+2)%2:1-4*b.abs(b.round(T/z)-T/z):W(T),S=(u?1-x+x*W(z*P/u):1)*(S<0?-1:1)*b.abs(S)**r*(P<l?P/l:P<l+v?1-(P-l)/v*(1-w):P<l+v+n?w:P<A-g?(A-P-g)/i*w:0),S=g?S/2+(g>P?0:(P<A-g?1:(A-P)/g)*t[P-g|0]/2/e):S,y&&(S=$=V*G+O*(G=R)+V*(R=S)-B*Y-q*(Y=$))),T+=(M=(a+=s+=f)*b.cos(h*C++))+M*p*W(P**5),I&&++I>c&&(a+=d,E+=d,I=0),!u||++D%u||(a=E,s=k,I=I||1);(e=zzfxX.createBuffer(1,A,44100)).getChannelData(0).set(t),(a=zzfxX.createBufferSource()).buffer=e,a.connect(zzfxX.destination),a.start()}),c=(t=Object.assign({width:null,height:null,autoscale:!0,canvas:null,global:!0,loop:null,tapEvents:!0,keyboardEvents:!0},t)).loop,u,p,h,m=1,g,w=.5,v=1,x,y=1e3/60,b,z=0,k=3,E="sans-serif",T=20,C=1.2,P=Date.now(),I=e,D=e,L=[],S=[.5,0,1750,,,.3,1,,,,600,.1],A={},M={W:0,H:0,T:0,MX:-1,MY:-1,TAU:o,lerp:(e,t,a)=>e+a*(t-e),deg2rad:e=>n.PI/180*e,rad2deg:e=>180/n.PI*e,mod:(e,t)=>(e%t+t)%t||0,round:(e,t=0)=>{if(!t)return n.round(e);let a=10**t;return n.round(e*a)/a},clamp:(e,t,a)=>e<t?t:e>a?a:e,dist:(e,t,a,l)=>n.hypot(a-e,l-t),wrap:(e,t,a)=>e-(a-t)*n.floor((e-t)/(a-t)),map(e,t,a,l,n,i){let o=(e-t)/(a-t)*(n-l)+l;return i?M.clamp(o,l,n):o},norm:(e,t,a)=>M.map(e,t,a,0,1),rand:(e=0,t=1)=>(P=(1664525*P+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>~~M.rand(e,t+1),rseed(e){P=~~e},cls(e){null==e?g.clearRect(0,0,M.W,M.H):M.rectfill(0,0,M.W,M.H,e)},rect(e,t,a,l,n,i){g.beginPath(),g[i?"roundRect":"rect"](~~e-w,~~t-w,~~a+2*w,~~l+2*w,i),M.stroke(n)},rectfill(e,t,a,l,n,i){g.beginPath(),g[i?"roundRect":"rect"](~~e,~~t,~~a,~~l,i),M.fill(n)},oval(e,t,a,l,n){g.beginPath(),g.ellipse(~~e,~~t,~~a,~~l,0,0,o),M.stroke(n)},ovalfill(e,t,a,l,n){g.beginPath(),g.ellipse(~~e,~~t,~~a,~~l,0,0,o),M.fill(n)},circ(e,t,a,l){M.oval(e,t,a,a,l)},circfill(e,t,a,l){M.ovalfill(e,t,a,a,l)},shape(e){g.beginPath();for(let t=0;t<e.length;t+=2)t?g.lineTo(~~e[t],~~e[t+1]):g.moveTo(~~e[t],~~e[t+1]);g.lineTo(~~e[0],~~e[1])},line(e,t,a,l,n){g.beginPath();let i=w&&~~e==~~a?.5:0,o=w&&~~t==~~l?.5:0;g.moveTo(~~e+i,~~t+o),g.lineTo(~~a+i,~~l+o),M.stroke(n)},linewidth(e){g.lineWidth=~~e,w=~~e%2?.5:0},linedash(e,t=0){g.setLineDash(e),g.lineDashOffset=t},text(e,t,a,l=k,n="normal"){g.font=`${n} ${T}px ${E}`,g.fillStyle=q(l);let i=(""+a).split("\n");for(let a=0;a<i.length;a++)g.fillText(i[a],~~e,~~t+T*C*a)},textgap(e){C=e},textfont(e){E=e},textsize(e){T=e},textalign(e,t){e&&(g.textAlign=e),t&&(g.textBaseline=t)},image(e,t,a){g.drawImage(a,~~e,~~t)},spr(e,t,a){let l=a.replace(/[^\w.\n]/g,"").split("\n").filter(e=>e);for(let a=0;a<l.length;a++)for(let n=0;n<l[a].length;n++)"."!==l[a][n]&&M.rectfill(e+n,t+a,1,1,parseInt(l[a][n],36)||0)},paint(e,t,a,l={}){let n=l.canvas||new OffscreenCanvas(1,1),i=l.scale||1,o=g;return n.width=e*i,n.height=t*i,(g=n.getContext("2d")).scale(i,i),a(g),g=o,n.transferToImageBitmap()},ctx:e=>(e&&(g=e),g),push(e=0,t=e,a=0,l=1,n=l){g.save(),M.translate(e,t),M.rotate(a),M.scale(l,n)},pop(){g.restore()},translate(e,t){g.translate(~~e,~~t)},scale(e,t=e){g.scale(e,t)},rotate(e){g.rotate(e)},alpha(e){g.globalAlpha=M.clamp(e,0,1)},fill(e){g.fillStyle=q(e),g.fill()},stroke(e){g.strokeStyle=q(e),g.stroke()},clip(e){g.beginPath(),e(g),g.clip()},sfx:(e,t,a)=>!!l.zzfxV&&(!navigator.userActivation||!!navigator.userActivation.hasBeenActive)&&(e||=S,(t||a>=0)&&((e=e.slice())[0]=a*(e[0]||1),e[10]=~~e[10]+t),d.apply(0,e),e),volume(e){l.zzfxV=e},canvas:()=>h,use(e,t={}){var a=e,l=t;let n=a(M,l);for(let e in n)M.def(e,n[e])},resize(e,a=e,l){t.width=e,t.height=a,t.autoscale=null==l?t.autoscale:l,X()},listen:(e,t)=>{A[e=e.toLowerCase()]=A[e]||new Set,A[e].add(t)},unlisten:(e,t)=>{A[e=e.toLowerCase()]&&A[e].delete(t)},emit:(e,t,a,n,i)=>(u&&(H("before:"+(e=e.toLowerCase()),t,a,n,i),c||l[e]===M[e]||"function"!=typeof l[e]||l[e](t,a,n,i),H(e,t,a,n,i),H("after:"+e,t,a,n,i)),t),pal(e,t=3){null==e?I=D:(D=I,I=e),L=[],k=t,M.emit("pal",I,k)},palc(e,t){null==e?L=[]:L[e]=t},def(e,a){M[e]=a,t.global&&(l[e]=a)},timescale(e){v=e},framerate(e){y=1e3/~~e},stat:e=>[t,u,y/1e3,m,A,I,S,v,l.zzfxV,P,T,E,L,C][e],ispaused:()=>p,pause(){p||(p=!0,z=~~cancelAnimationFrame(z),M.emit("paused"))},resume(){u&&p&&(N(),p=!1,M.emit("resumed"))},quit(){for(let e of(M.emit("quit"),M.pause(),u=!1,A={},s))e();if(t.global){for(let e in M)delete l[e];delete l.ENGINE}}};for(let e of"PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,min,max,pow,sqrt,sign".split(","))M[e]=n[e];function N(){z||(b=0,x=i.now(),z=r(W))}function W(){z=r(W);let e=i.now(),t=0,a=e-x;for(x=e,b+=a<100?a:y;b>=y;){t++,b-=y;let e=y/1e3*v;M.emit("update",e,t),M.def("T",M.T+e)}t&&(M.emit("draw",g),t>1&&(b=0))}function X(){let e=t.width>0?t.width:innerWidth,a=t.width>0?t.height||t.width:innerHeight;if(M.def("W",e),M.def("H",a),h.width=e,h.height=a,h.style="image-rendering:pixelated",t.autoscale){let l=+t.autoscale;h.style.display||(h.style.display="block",h.style.margin="auto"),m=n.min(innerWidth/e,innerHeight/a),m=l>1&&m>l?l:m,h.style.width=e*m+"px",h.style.height=a*m+"px"}g.imageSmoothingEnabled=!1,M.textalign("start","top"),M.emit("resized",m)}function H(e,t,a,l,n){if(A[e])for(let i of A[e])i(t,a,l,n)}function q(e){return e>=0?I[~~(L[e]??e)%I.length]:e}if(t.global){if(l.ENGINE)throw Error("only one global litecanvas is allowed");Object.assign(l,M),l.ENGINE=M}if(a=document,g=(h=(h="string"==typeof t.canvas?a.querySelector(t.canvas):t.canvas)||a.createElement("canvas")).getContext("2d"),f(h,"click",()=>focus()),h.parentNode||a.body.appendChild(h),h.oncontextmenu=()=>!1,X(),c)for(let e in c)c[e]&&M.listen(e,c[e]);return r(function(){if(t.autoscale&&f(l,"resize",X),t.tapEvents){let e=e=>[(e.pageX-h.offsetLeft)/m,(e.pageY-h.offsetTop)/m],t=new Map,a=(e,a,l)=>{let n={x:a,y:l,xi:a,yi:l,t:i.now()};return t.set(e,n),n},n=(e,l,n)=>{let i=t.get(e)||a(e);i.x=l,i.y=n},o=e=>e&&i.now()-e.t<=300,r=!1;f(h,"mousedown",t=>{if(!t.button){t.preventDefault();let[l,n]=e(t);M.emit("tap",l,n,0),a(0,l,n),r=!0}}),f(h,"mouseup",a=>{if(!a.button){a.preventDefault();let l=t.get(0),[n,i]=e(a);o(l)&&M.emit("tapped",l.xi,l.yi,0),M.emit("untap",n,i,0),t.delete(0),r=!1}}),f(l,"mousemove",t=>{t.preventDefault();let[a,l]=e(t);M.def("MX",a),M.def("MY",l),r&&(M.emit("tapping",a,l,0),n(0,a,l))}),f(h,"touchstart",t=>{for(let l of(t.preventDefault(),t.changedTouches)){let[t,n]=e(l);M.emit("tap",t,n,l.identifier+1),a(l.identifier+1,t,n)}}),f(h,"touchmove",t=>{for(let a of(t.preventDefault(),t.changedTouches)){let[t,l]=e(a);M.emit("tapping",t,l,a.identifier+1),n(a.identifier+1,t,l)}});let s=e=>{e.preventDefault();let a=[];for(let t of e.targetTouches)a.push(t.identifier+1);for(let[e,l]of t)a.includes(e)||(o(l)&&M.emit("tapped",l.xi,l.yi,e),M.emit("untap",l.x,l.y,e),t.delete(e))};f(h,"touchend",s),f(h,"touchcancel",s),f(l,"blur",()=>{for(let[e,a]of(r=!1,t))M.emit("untap",a.x,a.y,e),t.delete(e)})}if(t.keyboardEvents){let e=new Set,t=new Set,a=(e,t="")=>(t=t.toLowerCase())?e.has("space"===t?" ":t):e.size>0,n="";f(l,"keydown",a=>{let l=a.key.toLowerCase();e.has(l)||(e.add(l),t.add(l),n=" "===l?"space":l)}),f(l,"keyup",t=>{e.delete(t.key.toLowerCase())}),f(l,"blur",()=>e.clear()),M.listen("after:update",()=>t.clear()),M.def("iskeydown",t=>a(e,t)),M.def("iskeypressed",e=>a(t,e)),M.def("lastkey",()=>n)}u=!0,M.emit("init",M),p||N()}),M}})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "litecanvas",
3
- "version": "0.302.0",
3
+ "version": "0.400.0",
4
4
  "description": "Lightweight HTML5 canvas 2D game engine suitable for small projects and creative coding. Inspired by PICO-8 and p5.js/Processing.",
5
5
  "license": "MIT",
6
6
  "author": "Luiz Bills <luizbills@pm.me>",
@@ -32,16 +32,16 @@
32
32
  "creative coding"
33
33
  ],
34
34
  "devDependencies": {
35
- "@happy-dom/global-registrator": "^20.10.4",
36
- "@size-limit/preset-small-lib": "^12.1.0",
37
- "@swc/core": "^1.15.41",
35
+ "@happy-dom/global-registrator": "^21.0.1",
36
+ "@size-limit/preset-small-lib": "^14.2.0",
37
+ "@swc/core": "^1.16.18",
38
38
  "ava": "^8.0.1",
39
- "esbuild": "^0.28.1",
39
+ "esbuild": "^0.28.2",
40
40
  "genversion": "^3.2.0",
41
41
  "gzip-size": "^7.0.0",
42
- "prettier": "^3.8.4",
43
- "sinon": "^22.0.0",
44
- "size-limit": "^12.1.0",
42
+ "prettier": "^3.9.10",
43
+ "sinon": "^22.1.0",
44
+ "size-limit": "^14.2.0",
45
45
  "tap-min": "^3.0.0"
46
46
  },
47
47
  "trustedDependencies": [
package/src/index.js CHANGED
@@ -364,12 +364,12 @@ export default function litecanvas(settings = {}) {
364
364
  /**
365
365
  * Clear the game screen with an optional color.
366
366
  *
367
- * @param {number} [color] The background color (index) or null/undefined (for transparent)
367
+ * @param {number|string} [color] The background color (index) or null/undefined (for transparent)
368
368
  */
369
369
  cls(color) {
370
370
  DEV: assert(
371
- null == color || (isNumber(color) && color >= 0),
372
- 'cls() 1st argument must be a non-negative number'
371
+ null == color || (isNumber(color) && color >= 0) || 'string' === typeof color,
372
+ 'cls() 1st argument must be a non-negative number or string'
373
373
  )
374
374
 
375
375
  if (null == color) {
@@ -386,7 +386,7 @@ export default function litecanvas(settings = {}) {
386
386
  * @param {number} y
387
387
  * @param {number} width
388
388
  * @param {number} height
389
- * @param {number} [color=0] the color index
389
+ * @param {number|string} [color=0] the color index
390
390
  * @param {number|number[]} [radii] A number or list specifying the radii used to draw a rounded-borders rectangle
391
391
  *
392
392
  * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/roundRect
@@ -403,8 +403,8 @@ export default function litecanvas(settings = {}) {
403
403
  'rect() 4th argument must be a non-negative number'
404
404
  )
405
405
  DEV: assert(
406
- null == color || (isNumber(color) && color >= 0),
407
- 'rect() 5th argument must be a non-negative number'
406
+ null == color || (isNumber(color) && color >= 0) || 'string' === typeof color,
407
+ 'rect() 5th argument must be a non-negative number or string'
408
408
  )
409
409
  DEV: assert(
410
410
  null == radii || isNumber(radii) || (Array.isArray(radii) && radii.length >= 1),
@@ -430,7 +430,7 @@ export default function litecanvas(settings = {}) {
430
430
  * @param {number} y
431
431
  * @param {number} width
432
432
  * @param {number} height
433
- * @param {number} [color=0] the color index
433
+ * @param {number|string} [color=0] the color index
434
434
  * @param {number|number[]} [radii] A number or list specifying the radii used to draw a rounded-borders rectangle
435
435
  */
436
436
  rectfill(x, y, width, height, color, radii) {
@@ -445,8 +445,8 @@ export default function litecanvas(settings = {}) {
445
445
  'rectfill() 4th argument must be a non-negative number'
446
446
  )
447
447
  DEV: assert(
448
- null == color || (isNumber(color) && color >= 0),
449
- 'rectfill() 5th argument must be a non-negative number'
448
+ null == color || (isNumber(color) && color >= 0) || 'string' === typeof color,
449
+ 'rectfill() 5th argument must be a non-negative number or string'
450
450
  )
451
451
  DEV: assert(
452
452
  null == radii || isNumber(radii) || (Array.isArray(radii) && radii.length >= 1),
@@ -467,7 +467,7 @@ export default function litecanvas(settings = {}) {
467
467
  * @param {number} y
468
468
  * @param {number} radiusX
469
469
  * @param {number} radiusY
470
- * @param {number} [color=0] the color index
470
+ * @param {number|string} [color=0] the color index
471
471
  */
472
472
  oval(x, y, radiusX, radiusY, color) {
473
473
  DEV: assert(isNumber(x), 'oval() 1st argument must be a number')
@@ -481,8 +481,8 @@ export default function litecanvas(settings = {}) {
481
481
  'oval() 4th argument must be a non-negative number'
482
482
  )
483
483
  DEV: assert(
484
- null == color || (isNumber(color) && color >= 0),
485
- 'oval() 5th argument must be a non-negative number'
484
+ null == color || (isNumber(color) && color >= 0) || 'string' === typeof color,
485
+ 'oval() 5th argument must be a non-negative number or string'
486
486
  )
487
487
 
488
488
  beginPath(_ctx)
@@ -498,7 +498,7 @@ export default function litecanvas(settings = {}) {
498
498
  * @param {number} y
499
499
  * @param {number} radiusX
500
500
  * @param {number} radiusY
501
- * @param {number} [color=0] the color index
501
+ * @param {number|string} [color=0] the color index
502
502
  */
503
503
  ovalfill(x, y, radiusX, radiusY, color) {
504
504
  DEV: assert(isNumber(x), 'ovalfill() 1st argument must be a number')
@@ -512,8 +512,8 @@ export default function litecanvas(settings = {}) {
512
512
  'ovalfill() 4th argument must be a non-negative number'
513
513
  )
514
514
  DEV: assert(
515
- null == color || (isNumber(color) && color >= 0),
516
- 'ovalfill() 5th argument must be a non-negative number'
515
+ null == color || (isNumber(color) && color >= 0) || 'string' === typeof color,
516
+ 'ovalfill() 5th argument must be a non-negative number or string'
517
517
  )
518
518
 
519
519
  beginPath(_ctx)
@@ -528,7 +528,7 @@ export default function litecanvas(settings = {}) {
528
528
  * @param {number} x
529
529
  * @param {number} y
530
530
  * @param {number} radius
531
- * @param {number} [color=0] the color index
531
+ * @param {number|string} [color=0] the color index
532
532
  */
533
533
  circ(x, y, radius, color) {
534
534
  DEV: assert(isNumber(x), 'circ() 1st argument must be a number')
@@ -538,8 +538,8 @@ export default function litecanvas(settings = {}) {
538
538
  'circ() 3rd argument must be a non-negative number'
539
539
  )
540
540
  DEV: assert(
541
- null == color || (isNumber(color) && color >= 0),
542
- 'circ() 4th argument must be a non-negative number'
541
+ null == color || (isNumber(color) && color >= 0) || 'string' === typeof color,
542
+ 'circ() 4th argument must be a non-negative number or string'
543
543
  )
544
544
 
545
545
  instance.oval(x, y, radius, radius, color)
@@ -551,7 +551,7 @@ export default function litecanvas(settings = {}) {
551
551
  * @param {number} x
552
552
  * @param {number} y
553
553
  * @param {number} radius
554
- * @param {number} [color=0] the color index
554
+ * @param {number|string} [color=0] the color index
555
555
  */
556
556
  circfill(x, y, radius, color) {
557
557
  DEV: assert(isNumber(x), 'circfill() 1st argument must be a number')
@@ -561,8 +561,8 @@ export default function litecanvas(settings = {}) {
561
561
  'circfill() 3rd argument must be a non-negative number'
562
562
  )
563
563
  DEV: assert(
564
- null == color || (isNumber(color) && color >= 0),
565
- 'circfill() 4th argument must be a non-negative number'
564
+ null == color || (isNumber(color) && color >= 0) || 'string' === typeof color,
565
+ 'circfill() 4th argument must be a non-negative number or string'
566
566
  )
567
567
 
568
568
  instance.ovalfill(x, y, radius, radius, color)
@@ -600,7 +600,7 @@ export default function litecanvas(settings = {}) {
600
600
  * @param {number} y1
601
601
  * @param {number} x2
602
602
  * @param {number} y2
603
- * @param {number} [color=0] the color index
603
+ * @param {number|string} [color=0] the color index
604
604
  */
605
605
  line(x1, y1, x2, y2, color) {
606
606
  DEV: assert(isNumber(x1), 'line() 1st argument must be a number')
@@ -608,8 +608,8 @@ export default function litecanvas(settings = {}) {
608
608
  DEV: assert(isNumber(x2), 'line() 3rd argument must be a non-negative number')
609
609
  DEV: assert(isNumber(y2), 'line() 4th argument must be a non-negative number')
610
610
  DEV: assert(
611
- null == color || (isNumber(color) && color >= 0),
612
- 'line() 5th argument must be a non-negative number'
611
+ null == color || (isNumber(color) && color >= 0) || 'string' === typeof color,
612
+ 'line() 5th argument must be a non-negative number or string'
613
613
  )
614
614
 
615
615
  beginPath(_ctx)
@@ -665,15 +665,15 @@ export default function litecanvas(settings = {}) {
665
665
  * @param {number} x
666
666
  * @param {number} y
667
667
  * @param {string} message the text message
668
- * @param {number} [color] the color index
668
+ * @param {number|string} [color] the color index
669
669
  * @param {string} [fontStyle] can be "normal" (default), "italic" and/or "bold".
670
670
  */
671
671
  text(x, y, message, color = _defaultTextColor, fontStyle = 'normal') {
672
672
  DEV: assert(isNumber(x), 'text() 1st argument must be a number')
673
673
  DEV: assert(isNumber(y), 'text() 2nd argument must be a number')
674
674
  DEV: assert(
675
- null == color || (isNumber(color) && color >= 0),
676
- 'text() 4th argument must be a non-negative number'
675
+ null == color || (isNumber(color) && color >= 0) || 'string' === typeof color,
676
+ 'text() 4th argument must be a non-negative number or string'
677
677
  )
678
678
  DEV: assert('string' === typeof fontStyle, 'text() 5th argument must be a string')
679
679
 
@@ -947,12 +947,12 @@ export default function litecanvas(settings = {}) {
947
947
  /**
948
948
  * Fills the current path with a given color.
949
949
  *
950
- * @param {number} [color=0]
950
+ * @param {number|string} [color=0]
951
951
  */
952
952
  fill(color) {
953
953
  DEV: assert(
954
- null == color || (isNumber(color) && color >= 0),
955
- 'fill() 1st argument must be a non-negative number'
954
+ null == color || (isNumber(color) && color >= 0) || 'string' === typeof color,
955
+ 'fill() 1st argument must be a non-negative number or string'
956
956
  )
957
957
 
958
958
  _ctx.fillStyle = getColor(color)
@@ -962,12 +962,12 @@ export default function litecanvas(settings = {}) {
962
962
  /**
963
963
  * Outlines the current path with a given color.
964
964
  *
965
- * @param {number} [color=0]
965
+ * @param {number|string} [color=0]
966
966
  */
967
967
  stroke(color) {
968
968
  DEV: assert(
969
- null == color || (isNumber(color) && color >= 0),
970
- 'stroke() 1st argument must be a non-negative number'
969
+ null == color || (isNumber(color) && color >= 0) || 'string' === typeof color,
970
+ 'stroke() 1st argument must be a non-negative number or string'
971
971
  )
972
972
 
973
973
  _ctx.strokeStyle = getColor(color)
@@ -1427,7 +1427,7 @@ export default function litecanvas(settings = {}) {
1427
1427
  }
1428
1428
 
1429
1429
  // prettier-ignore
1430
- const mathProps = 'PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp'
1430
+ const mathProps = 'PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,min,max,pow,sqrt,sign'
1431
1431
  for (const k of mathProps.split(',')) {
1432
1432
  // import native Math functions
1433
1433
  instance[k] = math[k]
@@ -1867,12 +1867,13 @@ export default function litecanvas(settings = {}) {
1867
1867
  }
1868
1868
 
1869
1869
  /**
1870
- * @param {number} index
1870
+ * @param {number|string} color
1871
1871
  * @returns {string}
1872
1872
  */
1873
- function getColor(index) {
1874
- const i = _colorPaletteState[index] ?? index
1875
- return _currentPalette[~~i % _currentPalette.length]
1873
+ function getColor(color) {
1874
+ return color >= 0
1875
+ ? _currentPalette[~~(_colorPaletteState[color] ?? color) % _currentPalette.length]
1876
+ : color
1876
1877
  }
1877
1878
 
1878
1879
  if (settings.global) {
package/src/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '0.302.0'
2
+ export const version = '0.400.0'
package/types/global.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import './types'
1
+ import './types.d.ts'
2
2
 
3
3
  export default function litecanvas(settings?: LitecanvasOptions): LitecanvasInstance
4
4
 
@@ -162,10 +162,6 @@ declare global {
162
162
  * Always rounds down and returns the largest integer less than or equal to a given number.
163
163
  */
164
164
  function floor(n: number): number
165
- /**
166
- * Returns the integer part of a number by removing any fractional digits.
167
- */
168
- function trunc(n: number): number
169
165
  /**
170
166
  * Returns the smallest of the numbers given as input parameters, or `Infinity` if there are no parameters.
171
167
  */
@@ -187,10 +183,6 @@ declare global {
187
183
  * If the input is 0 or -0, it will be returned as-is.
188
184
  */
189
185
  function sign(n: number): number
190
- /**
191
- * Returns the Euler's number raised to the power of a number.
192
- */
193
- function exp(exponent: number): number
194
186
 
195
187
  /** RNG API */
196
188
  /**
@@ -224,7 +216,7 @@ declare global {
224
216
  *
225
217
  * @param color The background color index or `null`
226
218
  */
227
- function cls(color: number | null): void
219
+ function cls(color?: number | string): void
228
220
 
229
221
  /**
230
222
  * Draw a rectangle outline
@@ -243,7 +235,7 @@ declare global {
243
235
  y: number,
244
236
  width: number,
245
237
  height: number,
246
- color?: number,
238
+ color?: number | string,
247
239
  radii?: number | number[]
248
240
  ): void
249
241
  /**
@@ -261,7 +253,7 @@ declare global {
261
253
  y: number,
262
254
  width: number,
263
255
  height: number,
264
- color?: number,
256
+ color?: number | string,
265
257
  radii?: number | number[]
266
258
  ): void
267
259
  /**
@@ -272,7 +264,7 @@ declare global {
272
264
  * @param radius
273
265
  * @param [color=0] the color index
274
266
  */
275
- function circ(x: number, y: number, radius: number, color?: number): void
267
+ function circ(x: number, y: number, radius: number, color?: number | string): void
276
268
  /**
277
269
  * Draw a color-filled circle
278
270
  *
@@ -281,7 +273,7 @@ declare global {
281
273
  * @param radius
282
274
  * @param [color=0] the color index
283
275
  */
284
- function circfill(x: number, y: number, radius: number, color?: number): void
276
+ function circfill(x: number, y: number, radius: number, color?: number | string): void
285
277
  /**
286
278
  * Draw a ellipse outline
287
279
  *
@@ -291,7 +283,13 @@ declare global {
291
283
  * @param radiusY
292
284
  * @param [color=0] the color index
293
285
  */
294
- function oval(x: number, y: number, radiusX: number, radiusY: number, color?: number): void
286
+ function oval(
287
+ x: number,
288
+ y: number,
289
+ radiusX: number,
290
+ radiusY: number,
291
+ color?: number | string
292
+ ): void
295
293
  /**
296
294
  * Draw a color-filled ellipse
297
295
  *
@@ -301,7 +299,13 @@ declare global {
301
299
  * @param radiusY
302
300
  * @param [color=0] the color index
303
301
  */
304
- function ovalfill(x: number, y: number, radiusX: number, radiusY: number, color?: number): void
302
+ function ovalfill(
303
+ x: number,
304
+ y: number,
305
+ radiusX: number,
306
+ radiusY: number,
307
+ color?: number | string
308
+ ): void
305
309
  /**
306
310
  * Make a custom shape in the canvas context.
307
311
  * Then, just use `fill` or `stroke` to draw the shape.
@@ -324,7 +328,7 @@ declare global {
324
328
  * @param y2
325
329
  * @param [color=0] the color index
326
330
  */
327
- function line(x1: number, y1: number, x2: number, y2: number, color?: number): void
331
+ function line(x1: number, y1: number, x2: number, y2: number, color?: number | string): void
328
332
  /**
329
333
  * Sets the thickness of lines
330
334
  *
@@ -352,7 +356,13 @@ declare global {
352
356
  * @param [color=3] the color index
353
357
  * @param [fontStyle="normal"] can be "normal" (default), "italic" and/or "bold"
354
358
  */
355
- function text(x: number, y: number, message: string, color?: number, fontStyle?: string): void
359
+ function text(
360
+ x: number,
361
+ y: number,
362
+ message: string,
363
+ color?: number | string,
364
+ fontStyle?: string
365
+ ): void
356
366
  /**
357
367
  * Set the font family
358
368
  *
@@ -506,13 +516,13 @@ declare global {
506
516
  *
507
517
  * @param color
508
518
  */
509
- function fill(color: number): void
519
+ function fill(color?: number | string): void
510
520
  /**
511
521
  * Outlines the current path with a given color.
512
522
  *
513
523
  * @param color
514
524
  */
515
- function stroke(color: number): void
525
+ function stroke(color?: number | string): void
516
526
  /**
517
527
  * Turns a path (in the callback) into the current clipping region.
518
528
  *
package/types/types.d.ts CHANGED
@@ -156,10 +156,6 @@ type LitecanvasInstance = {
156
156
  * Always rounds down and returns the largest integer less than or equal to a given number.
157
157
  */
158
158
  floor?(n: number): number
159
- /**
160
- * Returns the integer part of a number by removing any fractional digits.
161
- */
162
- trunc?(n: number): number
163
159
  /**
164
160
  * Returns the smallest of the numbers given as input parameters, or `Infinity` if there are no parameters.
165
161
  */
@@ -181,10 +177,6 @@ type LitecanvasInstance = {
181
177
  * If the input is 0 or -0, it will be returned as-is.
182
178
  */
183
179
  sign?(n: number): number
184
- /**
185
- * Returns the Euler's number raised to the power of a number.
186
- */
187
- exp?(exponent: number): number
188
180
 
189
181
  /** RNG API */
190
182
  /**
@@ -218,7 +210,7 @@ type LitecanvasInstance = {
218
210
  *
219
211
  * @param color The background color index or `null`
220
212
  */
221
- cls(color: number | null): void
213
+ cls(color?: number | string): void
222
214
 
223
215
  /**
224
216
  * Draw a rectangle outline
@@ -237,7 +229,7 @@ type LitecanvasInstance = {
237
229
  y: number,
238
230
  width: number,
239
231
  height: number,
240
- color?: number,
232
+ color?: number | string,
241
233
  radii?: number | number[]
242
234
  ): void
243
235
  /**
@@ -255,7 +247,7 @@ type LitecanvasInstance = {
255
247
  y: number,
256
248
  width: number,
257
249
  height: number,
258
- color?: number,
250
+ color?: number | string,
259
251
  radii?: number | number[]
260
252
  ): void
261
253
  /**
@@ -266,7 +258,7 @@ type LitecanvasInstance = {
266
258
  * @param radius
267
259
  * @param [color=0] the color index
268
260
  */
269
- circ(x: number, y: number, radius: number, color?: number): void
261
+ circ(x: number, y: number, radius: number, color?: number | string): void
270
262
  /**
271
263
  * Draw a color-filled circle
272
264
  *
@@ -275,7 +267,7 @@ type LitecanvasInstance = {
275
267
  * @param radius
276
268
  * @param [color=0] the color index
277
269
  */
278
- circfill(x: number, y: number, radius: number, color?: number): void
270
+ circfill(x: number, y: number, radius: number, color?: number | string): void
279
271
  /**
280
272
  * Draw a ellipse outline
281
273
  *
@@ -285,7 +277,7 @@ type LitecanvasInstance = {
285
277
  * @param radiusY
286
278
  * @param [color=0] the color index
287
279
  */
288
- oval(x: number, y: number, radiusX: number, radiusY: number, color?: number): void
280
+ oval(x: number, y: number, radiusX: number, radiusY: number, color?: number | string): void
289
281
  /**
290
282
  * Draw a color-filled ellipse
291
283
  *
@@ -295,7 +287,7 @@ type LitecanvasInstance = {
295
287
  * @param radiusY
296
288
  * @param [color=0] the color index
297
289
  */
298
- ovalfill(x: number, y: number, radiusX: number, radiusY: number, color?: number): void
290
+ ovalfill(x: number, y: number, radiusX: number, radiusY: number, color?: number | string): void
299
291
  /**
300
292
  * Make a custom shape in the canvas context.
301
293
  * Then, just use `fill` or `stroke` to draw the shape.
@@ -312,7 +304,7 @@ type LitecanvasInstance = {
312
304
  * @param y2
313
305
  * @param [color=0] the color index
314
306
  */
315
- line(x1: number, y1: number, x2: number, y2: number, color?: number): void
307
+ line(x1: number, y1: number, x2: number, y2: number, color?: number | string): void
316
308
  /**
317
309
  * Sets the thickness of lines
318
310
  *
@@ -340,7 +332,7 @@ type LitecanvasInstance = {
340
332
  * @param [color=3] the color index
341
333
  * @param [fontStyle="normal"] can be "normal" (default), "italic" and/or "bold"
342
334
  */
343
- text(x: number, y: number, message: string, color?: number, fontStyle?: string): void
335
+ text(x: number, y: number, message: string, color?: number | string, fontStyle?: string): void
344
336
  /**
345
337
  * Set the font family
346
338
  *
@@ -494,13 +486,13 @@ type LitecanvasInstance = {
494
486
  *
495
487
  * @param color
496
488
  */
497
- fill(color: number): void
489
+ fill(color?: number | string): void
498
490
  /**
499
491
  * Outlines the current path with a given color.
500
492
  *
501
493
  * @param color
502
494
  */
503
- stroke(color: number): void
495
+ stroke(color?: number | string): void
504
496
  /**
505
497
  * Turns a path (in the callback) into the current clipping region.
506
498
  *