litecanvas 0.87.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.dev.js +60 -70
- package/dist/dist.js +57 -55
- package/dist/dist.min.js +1 -1
- package/package.json +42 -28
- package/src/index.js +72 -83
- package/types/index.d.ts +22 -21
- package/types/types.d.ts +23 -20
package/dist/dist.dev.js
CHANGED
|
@@ -32,14 +32,14 @@
|
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
// version.js
|
|
35
|
-
var version = "0.
|
|
35
|
+
var version = "0.88.0";
|
|
36
36
|
|
|
37
37
|
// src/index.js
|
|
38
38
|
function litecanvas(settings = {}) {
|
|
39
39
|
const root = window, math = Math, TWO_PI = math.PI * 2, raf = requestAnimationFrame, _browserEventListeners = [], on = (elem, evt, callback) => {
|
|
40
40
|
elem.addEventListener(evt, callback, false);
|
|
41
41
|
_browserEventListeners.push(() => elem.removeEventListener(evt, callback, false));
|
|
42
|
-
}, isNumber = Number.isFinite, zzfx = setupZzFX(root), defaults = {
|
|
42
|
+
}, beginPath = (c) => c.beginPath(), isNumber = Number.isFinite, zzfx = setupZzFX(root), defaults = {
|
|
43
43
|
width: null,
|
|
44
44
|
height: null,
|
|
45
45
|
autoscale: true,
|
|
@@ -339,7 +339,7 @@
|
|
|
339
339
|
null == radii || isNumber(radii) || Array.isArray(radii) && radii.length >= 1,
|
|
340
340
|
"[litecanvas] rect() 6th param must be a number or array of numbers"
|
|
341
341
|
);
|
|
342
|
-
|
|
342
|
+
beginPath(_ctx);
|
|
343
343
|
_ctx[radii ? "roundRect" : "rect"](
|
|
344
344
|
~~x - _outline_fix,
|
|
345
345
|
~~y - _outline_fix,
|
|
@@ -378,7 +378,7 @@
|
|
|
378
378
|
null == radii || isNumber(radii) || Array.isArray(radii) && radii.length >= 1,
|
|
379
379
|
"[litecanvas] rectfill() 6th param must be a number or array of at least 2 numbers"
|
|
380
380
|
);
|
|
381
|
-
|
|
381
|
+
beginPath(_ctx);
|
|
382
382
|
_ctx[radii ? "roundRect" : "rect"](~~x, ~~y, ~~width, ~~height, radii);
|
|
383
383
|
instance.fill(color);
|
|
384
384
|
},
|
|
@@ -401,7 +401,7 @@
|
|
|
401
401
|
null == color || isNumber(color) && color >= 0,
|
|
402
402
|
"[litecanvas] circ() 4th param must be a positive number or zero"
|
|
403
403
|
);
|
|
404
|
-
|
|
404
|
+
beginPath(_ctx);
|
|
405
405
|
_ctx.arc(~~x, ~~y, ~~radius, 0, TWO_PI);
|
|
406
406
|
instance.stroke(color);
|
|
407
407
|
},
|
|
@@ -424,7 +424,7 @@
|
|
|
424
424
|
null == color || isNumber(color) && color >= 0,
|
|
425
425
|
"[litecanvas] circfill() 4th param must be a positive number or zero"
|
|
426
426
|
);
|
|
427
|
-
|
|
427
|
+
beginPath(_ctx);
|
|
428
428
|
_ctx.arc(~~x, ~~y, ~~radius, 0, TWO_PI);
|
|
429
429
|
instance.fill(color);
|
|
430
430
|
},
|
|
@@ -452,7 +452,7 @@
|
|
|
452
452
|
null == color || isNumber(color) && color >= 0,
|
|
453
453
|
"[litecanvas] oval() 5th param must be a positive number or zero"
|
|
454
454
|
);
|
|
455
|
-
|
|
455
|
+
beginPath(_ctx);
|
|
456
456
|
_ctx.ellipse(~~x, ~~y, ~~radiusX, ~~radiusY, 0, 0, TWO_PI);
|
|
457
457
|
instance.stroke(color);
|
|
458
458
|
},
|
|
@@ -480,7 +480,7 @@
|
|
|
480
480
|
null == color || isNumber(color) && color >= 0,
|
|
481
481
|
"[litecanvas] ovalfill() 5th param must be a positive number or zero"
|
|
482
482
|
);
|
|
483
|
-
|
|
483
|
+
beginPath(_ctx);
|
|
484
484
|
_ctx.ellipse(~~x, ~~y, ~~radiusX, ~~radiusY, 0, 0, TWO_PI);
|
|
485
485
|
instance.fill(color);
|
|
486
486
|
},
|
|
@@ -508,7 +508,7 @@
|
|
|
508
508
|
null == color || isNumber(color) && color >= 0,
|
|
509
509
|
"[litecanvas] line() 5th param must be a positive number or zero"
|
|
510
510
|
);
|
|
511
|
-
|
|
511
|
+
beginPath(_ctx);
|
|
512
512
|
let xfix = _outline_fix !== 0 && ~~x1 === ~~x2 ? 0.5 : 0;
|
|
513
513
|
let yfix = _outline_fix !== 0 && ~~y1 === ~~y2 ? 0.5 : 0;
|
|
514
514
|
_ctx.moveTo(~~x1 + xfix, ~~y1 + yfix);
|
|
@@ -752,79 +752,45 @@
|
|
|
752
752
|
_ctx.globalAlpha = instance.clamp(value, 0, 1);
|
|
753
753
|
},
|
|
754
754
|
/**
|
|
755
|
-
*
|
|
756
|
-
* path as an argument (creates a copy), or optionally with a string
|
|
757
|
-
* consisting of SVG path data.
|
|
758
|
-
*
|
|
759
|
-
* @param {Path2D|string} [arg]
|
|
760
|
-
* @returns Path2D
|
|
761
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/API/Path2D/Path2D
|
|
762
|
-
*/
|
|
763
|
-
path: (arg) => {
|
|
764
|
-
DEV: assert(
|
|
765
|
-
null == arg || "string" === typeof arg || arg instanceof Path2D,
|
|
766
|
-
"[litecanvas] path() 1st param must be a string or a Path2D instance"
|
|
767
|
-
);
|
|
768
|
-
return new Path2D(arg);
|
|
769
|
-
},
|
|
770
|
-
/**
|
|
771
|
-
* Fills the current or given path with a given color.
|
|
755
|
+
* Fills the current path with a given color.
|
|
772
756
|
*
|
|
773
757
|
* @param {number} [color=0]
|
|
774
|
-
* @param {Path2D} [path]
|
|
775
758
|
*/
|
|
776
|
-
fill(color
|
|
759
|
+
fill(color) {
|
|
777
760
|
DEV: assert(
|
|
778
761
|
null == color || isNumber(color) && color >= 0,
|
|
779
762
|
"[litecanvas] fill() 1st param must be a positive number or zero"
|
|
780
763
|
);
|
|
781
|
-
DEV: assert(
|
|
782
|
-
null == path || path instanceof Path2D,
|
|
783
|
-
"[litecanvas] fill() 2nd param must be a Path2D instance"
|
|
784
|
-
);
|
|
785
764
|
_ctx.fillStyle = _colors[~~color % _colors.length];
|
|
786
|
-
|
|
787
|
-
_ctx.fill(path);
|
|
788
|
-
} else {
|
|
789
|
-
_ctx.fill();
|
|
790
|
-
}
|
|
765
|
+
_ctx.fill();
|
|
791
766
|
},
|
|
792
767
|
/**
|
|
793
|
-
* Outlines the current
|
|
768
|
+
* Outlines the current path with a given color.
|
|
794
769
|
*
|
|
795
770
|
* @param {number} [color=0]
|
|
796
|
-
* @param {Path2D} [path]
|
|
797
771
|
*/
|
|
798
|
-
stroke(color
|
|
772
|
+
stroke(color) {
|
|
799
773
|
DEV: assert(
|
|
800
774
|
null == color || isNumber(color) && color >= 0,
|
|
801
775
|
"[litecanvas] stroke() 1st param must be a positive number or zero"
|
|
802
776
|
);
|
|
803
|
-
DEV: assert(
|
|
804
|
-
null == path || path instanceof Path2D,
|
|
805
|
-
"[litecanvas] stroke() 2nd param must be a Path2D instance"
|
|
806
|
-
);
|
|
807
777
|
_ctx.strokeStyle = _colors[~~color % _colors.length];
|
|
808
|
-
|
|
809
|
-
_ctx.stroke(path);
|
|
810
|
-
} else {
|
|
811
|
-
_ctx.stroke();
|
|
812
|
-
}
|
|
778
|
+
_ctx.stroke();
|
|
813
779
|
},
|
|
814
780
|
/**
|
|
815
|
-
*
|
|
816
|
-
*
|
|
817
|
-
* Note: always call `push()` before and `pop()` after.
|
|
781
|
+
* Turns a path (in the callback) into the current clipping region.
|
|
818
782
|
*
|
|
819
|
-
* @param {
|
|
783
|
+
* @param {clipCallback} callback
|
|
820
784
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clip
|
|
821
785
|
*/
|
|
822
|
-
clip(
|
|
786
|
+
clip(callback) {
|
|
823
787
|
DEV: assert(
|
|
824
|
-
|
|
825
|
-
"[litecanvas] clip() 1st param must be a
|
|
788
|
+
"function" === typeof callback,
|
|
789
|
+
"[litecanvas] clip() 1st param must be a function"
|
|
826
790
|
);
|
|
827
|
-
_ctx
|
|
791
|
+
beginPath(_ctx);
|
|
792
|
+
callback(_ctx);
|
|
793
|
+
_ctx.clip();
|
|
828
794
|
},
|
|
829
795
|
/** SOUND API */
|
|
830
796
|
/**
|
|
@@ -1007,7 +973,7 @@
|
|
|
1007
973
|
// 1
|
|
1008
974
|
_initialized,
|
|
1009
975
|
// 2
|
|
1010
|
-
|
|
976
|
+
_deltaTime,
|
|
1011
977
|
// 3
|
|
1012
978
|
_scale,
|
|
1013
979
|
// 4
|
|
@@ -1036,8 +1002,7 @@
|
|
|
1036
1002
|
* Stops the litecanvas instance and remove all event listeners.
|
|
1037
1003
|
*/
|
|
1038
1004
|
quit() {
|
|
1039
|
-
|
|
1040
|
-
_rafid = 0;
|
|
1005
|
+
instance.pause();
|
|
1041
1006
|
instance.emit("quit");
|
|
1042
1007
|
_eventListeners = {};
|
|
1043
1008
|
for (const removeListener of _browserEventListeners) {
|
|
@@ -1050,6 +1015,29 @@
|
|
|
1050
1015
|
delete root.ENGINE;
|
|
1051
1016
|
}
|
|
1052
1017
|
_initialized = false;
|
|
1018
|
+
},
|
|
1019
|
+
/**
|
|
1020
|
+
* Pauses the engine loop (update & draw).
|
|
1021
|
+
*/
|
|
1022
|
+
pause() {
|
|
1023
|
+
cancelAnimationFrame(_rafid);
|
|
1024
|
+
_rafid = 0;
|
|
1025
|
+
},
|
|
1026
|
+
/**
|
|
1027
|
+
* Resumes (if paused) the engine loop.
|
|
1028
|
+
*/
|
|
1029
|
+
resume() {
|
|
1030
|
+
if (!_rafid && _initialized) {
|
|
1031
|
+
_rafid = raf(drawFrame);
|
|
1032
|
+
}
|
|
1033
|
+
},
|
|
1034
|
+
/**
|
|
1035
|
+
* Returns `true` if the engine loop is paused.
|
|
1036
|
+
*
|
|
1037
|
+
* @returns {boolean}
|
|
1038
|
+
*/
|
|
1039
|
+
paused() {
|
|
1040
|
+
return !_rafid;
|
|
1053
1041
|
}
|
|
1054
1042
|
};
|
|
1055
1043
|
for (const k of _mathFunctions.split(",")) {
|
|
@@ -1282,30 +1270,32 @@
|
|
|
1282
1270
|
}
|
|
1283
1271
|
_initialized = true;
|
|
1284
1272
|
instance.emit("init", instance);
|
|
1273
|
+
instance.textalign("start", "top");
|
|
1285
1274
|
_lastFrameTime = performance.now();
|
|
1286
|
-
|
|
1275
|
+
instance.resume();
|
|
1287
1276
|
}
|
|
1288
1277
|
function drawFrame(now) {
|
|
1278
|
+
if (!settings.animate) {
|
|
1279
|
+
return instance.emit("draw");
|
|
1280
|
+
}
|
|
1289
1281
|
let updated = 0;
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1282
|
+
let frameTime = (now - _lastFrameTime) / 1e3;
|
|
1283
|
+
_lastFrameTime = now;
|
|
1284
|
+
if (frameTime < 0.1) {
|
|
1285
|
+
_accumulated += frameTime;
|
|
1293
1286
|
while (_accumulated >= _deltaTime) {
|
|
1294
1287
|
updated++;
|
|
1295
1288
|
instance.emit("update", _deltaTime * _timeScale, updated);
|
|
1296
1289
|
instance.def("T", instance.T + _deltaTime * _timeScale);
|
|
1297
1290
|
_accumulated -= _deltaTime;
|
|
1298
1291
|
}
|
|
1299
|
-
if (_rafid) {
|
|
1300
|
-
_rafid = raf(drawFrame);
|
|
1301
|
-
}
|
|
1302
|
-
} else {
|
|
1303
|
-
updated = 1;
|
|
1304
1292
|
}
|
|
1305
1293
|
if (updated) {
|
|
1306
|
-
instance.textalign("start", "top");
|
|
1307
1294
|
instance.emit("draw");
|
|
1308
1295
|
}
|
|
1296
|
+
if (_rafid) {
|
|
1297
|
+
_rafid = raf(drawFrame);
|
|
1298
|
+
}
|
|
1309
1299
|
}
|
|
1310
1300
|
function setupCanvas() {
|
|
1311
1301
|
if ("string" === typeof settings.canvas) {
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
|
524
|
+
fill(color) {
|
|
538
525
|
_ctx.fillStyle = _colors[~~color % _colors.length];
|
|
539
|
-
|
|
540
|
-
_ctx.fill(path);
|
|
541
|
-
} else {
|
|
542
|
-
_ctx.fill();
|
|
543
|
-
}
|
|
526
|
+
_ctx.fill();
|
|
544
527
|
},
|
|
545
528
|
/**
|
|
546
|
-
* Outlines the current
|
|
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
|
|
533
|
+
stroke(color) {
|
|
552
534
|
_ctx.strokeStyle = _colors[~~color % _colors.length];
|
|
553
|
-
|
|
554
|
-
_ctx.stroke(path);
|
|
555
|
-
} else {
|
|
556
|
-
_ctx.stroke();
|
|
557
|
-
}
|
|
535
|
+
_ctx.stroke();
|
|
558
536
|
},
|
|
559
537
|
/**
|
|
560
|
-
*
|
|
538
|
+
* Turns a path (in the callback) into the current clipping region.
|
|
561
539
|
*
|
|
562
|
-
*
|
|
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(
|
|
568
|
-
_ctx
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
977
|
-
|
|
978
|
-
|
|
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) {
|
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,
|
|
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,23 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "litecanvas",
|
|
3
|
-
"version": "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": "^2.0.0",
|
|
10
|
-
"@swc/core": "^1.12.9",
|
|
11
|
-
"@types/jsdom": "^21.1.7",
|
|
12
|
-
"ava": "^6.4.0",
|
|
13
|
-
"esbuild": "^0.25.5",
|
|
14
|
-
"genversion": "^3.2.0",
|
|
15
|
-
"gzip-size": "^7.0.0",
|
|
16
|
-
"jsdom": "^26.1.0",
|
|
17
|
-
"prettier": "^3.6.2",
|
|
18
|
-
"sinon": "^21.0.0",
|
|
19
|
-
"tap-min": "^3.0.0"
|
|
20
|
-
},
|
|
21
8
|
"homepage": "https://litecanvas.github.io/about.html",
|
|
22
9
|
"repository": {
|
|
23
10
|
"type": "git",
|
|
@@ -29,18 +16,6 @@
|
|
|
29
16
|
"type": "module",
|
|
30
17
|
"main": "src/index.js",
|
|
31
18
|
"types": "types/index.d.ts",
|
|
32
|
-
"scripts": {
|
|
33
|
-
"test": "ava --timeout=1s --fast-fail --tap | tap-min",
|
|
34
|
-
"test:watch": "ava --watch",
|
|
35
|
-
"dev": "esbuild src/web.js --bundle --watch --outfile=dist/dist.dev.js --servedir=.",
|
|
36
|
-
"build": "npm run genversion && node script/build.js",
|
|
37
|
-
"gzip-size": "gzip -c dist/dist.min.js | wc -c | xargs printf \" Gzip size: %s bytes\n\"",
|
|
38
|
-
"format": "prettier -w src/* samples/* types/* script/* types/*",
|
|
39
|
-
"check-types": "npx ts types/*",
|
|
40
|
-
"genversion": "genversion --es6 --semi version.js",
|
|
41
|
-
"prepare": "npm run build",
|
|
42
|
-
"prepublishOnly": "npm test"
|
|
43
|
-
},
|
|
44
19
|
"keywords": [
|
|
45
20
|
"canvas",
|
|
46
21
|
"2d",
|
|
@@ -53,6 +28,36 @@
|
|
|
53
28
|
"pico-8",
|
|
54
29
|
"p5"
|
|
55
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
|
+
},
|
|
56
61
|
"files": [
|
|
57
62
|
"dist",
|
|
58
63
|
"src",
|
|
@@ -63,7 +68,16 @@
|
|
|
63
68
|
"tests/**/*.js"
|
|
64
69
|
]
|
|
65
70
|
},
|
|
66
|
-
"
|
|
67
|
-
|
|
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
|
+
}
|
|
68
82
|
]
|
|
69
83
|
}
|
package/src/index.js
CHANGED
|
@@ -23,6 +23,8 @@ export default function litecanvas(settings = {}) {
|
|
|
23
23
|
elem.addEventListener(evt, callback, false)
|
|
24
24
|
_browserEventListeners.push(() => elem.removeEventListener(evt, callback, false))
|
|
25
25
|
},
|
|
26
|
+
/** @type {(c: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D) => void} */
|
|
27
|
+
beginPath = (c) => c.beginPath(),
|
|
26
28
|
isNumber = Number.isFinite,
|
|
27
29
|
zzfx = setupZzFX(root),
|
|
28
30
|
/** @type {LitecanvasOptions} */
|
|
@@ -63,7 +65,7 @@ export default function litecanvas(settings = {}) {
|
|
|
63
65
|
_deltaTime = 1 / 60,
|
|
64
66
|
/** @type {number} */
|
|
65
67
|
_accumulated = 0,
|
|
66
|
-
/** @type {number
|
|
68
|
+
/** @type {number?} */
|
|
67
69
|
_rafid,
|
|
68
70
|
/** @type {string} */
|
|
69
71
|
_fontFamily = 'sans-serif',
|
|
@@ -406,7 +408,7 @@ export default function litecanvas(settings = {}) {
|
|
|
406
408
|
'[litecanvas] rect() 6th param must be a number or array of numbers'
|
|
407
409
|
)
|
|
408
410
|
|
|
409
|
-
|
|
411
|
+
beginPath(_ctx)
|
|
410
412
|
_ctx[radii ? 'roundRect' : 'rect'](
|
|
411
413
|
~~x - _outline_fix,
|
|
412
414
|
~~y - _outline_fix,
|
|
@@ -447,7 +449,7 @@ export default function litecanvas(settings = {}) {
|
|
|
447
449
|
'[litecanvas] rectfill() 6th param must be a number or array of at least 2 numbers'
|
|
448
450
|
)
|
|
449
451
|
|
|
450
|
-
|
|
452
|
+
beginPath(_ctx)
|
|
451
453
|
_ctx[radii ? 'roundRect' : 'rect'](~~x, ~~y, ~~width, ~~height, radii)
|
|
452
454
|
instance.fill(color)
|
|
453
455
|
},
|
|
@@ -472,7 +474,7 @@ export default function litecanvas(settings = {}) {
|
|
|
472
474
|
'[litecanvas] circ() 4th param must be a positive number or zero'
|
|
473
475
|
)
|
|
474
476
|
|
|
475
|
-
|
|
477
|
+
beginPath(_ctx)
|
|
476
478
|
_ctx.arc(~~x, ~~y, ~~radius, 0, TWO_PI)
|
|
477
479
|
instance.stroke(color)
|
|
478
480
|
},
|
|
@@ -497,7 +499,7 @@ export default function litecanvas(settings = {}) {
|
|
|
497
499
|
'[litecanvas] circfill() 4th param must be a positive number or zero'
|
|
498
500
|
)
|
|
499
501
|
|
|
500
|
-
|
|
502
|
+
beginPath(_ctx)
|
|
501
503
|
_ctx.arc(~~x, ~~y, ~~radius, 0, TWO_PI)
|
|
502
504
|
instance.fill(color)
|
|
503
505
|
},
|
|
@@ -527,7 +529,7 @@ export default function litecanvas(settings = {}) {
|
|
|
527
529
|
'[litecanvas] oval() 5th param must be a positive number or zero'
|
|
528
530
|
)
|
|
529
531
|
|
|
530
|
-
|
|
532
|
+
beginPath(_ctx)
|
|
531
533
|
_ctx.ellipse(~~x, ~~y, ~~radiusX, ~~radiusY, 0, 0, TWO_PI)
|
|
532
534
|
instance.stroke(color)
|
|
533
535
|
},
|
|
@@ -557,7 +559,7 @@ export default function litecanvas(settings = {}) {
|
|
|
557
559
|
'[litecanvas] ovalfill() 5th param must be a positive number or zero'
|
|
558
560
|
)
|
|
559
561
|
|
|
560
|
-
|
|
562
|
+
beginPath(_ctx)
|
|
561
563
|
_ctx.ellipse(~~x, ~~y, ~~radiusX, ~~radiusY, 0, 0, TWO_PI)
|
|
562
564
|
instance.fill(color)
|
|
563
565
|
},
|
|
@@ -587,7 +589,7 @@ export default function litecanvas(settings = {}) {
|
|
|
587
589
|
'[litecanvas] line() 5th param must be a positive number or zero'
|
|
588
590
|
)
|
|
589
591
|
|
|
590
|
-
|
|
592
|
+
beginPath(_ctx)
|
|
591
593
|
|
|
592
594
|
let xfix = _outline_fix !== 0 && ~~x1 === ~~x2 ? 0.5 : 0
|
|
593
595
|
let yfix = _outline_fix !== 0 && ~~y1 === ~~y2 ? 0.5 : 0
|
|
@@ -876,86 +878,50 @@ export default function litecanvas(settings = {}) {
|
|
|
876
878
|
},
|
|
877
879
|
|
|
878
880
|
/**
|
|
879
|
-
*
|
|
880
|
-
* path as an argument (creates a copy), or optionally with a string
|
|
881
|
-
* consisting of SVG path data.
|
|
882
|
-
*
|
|
883
|
-
* @param {Path2D|string} [arg]
|
|
884
|
-
* @returns Path2D
|
|
885
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/API/Path2D/Path2D
|
|
886
|
-
*/
|
|
887
|
-
path: (arg) => {
|
|
888
|
-
DEV: assert(
|
|
889
|
-
null == arg || 'string' === typeof arg || arg instanceof Path2D,
|
|
890
|
-
'[litecanvas] path() 1st param must be a string or a Path2D instance'
|
|
891
|
-
)
|
|
892
|
-
|
|
893
|
-
return new Path2D(arg)
|
|
894
|
-
},
|
|
895
|
-
|
|
896
|
-
/**
|
|
897
|
-
* Fills the current or given path with a given color.
|
|
881
|
+
* Fills the current path with a given color.
|
|
898
882
|
*
|
|
899
883
|
* @param {number} [color=0]
|
|
900
|
-
* @param {Path2D} [path]
|
|
901
884
|
*/
|
|
902
|
-
fill(color
|
|
885
|
+
fill(color) {
|
|
903
886
|
DEV: assert(
|
|
904
887
|
null == color || (isNumber(color) && color >= 0),
|
|
905
888
|
'[litecanvas] fill() 1st param must be a positive number or zero'
|
|
906
889
|
)
|
|
907
|
-
DEV: assert(
|
|
908
|
-
null == path || path instanceof Path2D,
|
|
909
|
-
'[litecanvas] fill() 2nd param must be a Path2D instance'
|
|
910
|
-
)
|
|
911
890
|
|
|
912
891
|
_ctx.fillStyle = _colors[~~color % _colors.length]
|
|
913
|
-
|
|
914
|
-
_ctx.fill(path)
|
|
915
|
-
} else {
|
|
916
|
-
_ctx.fill()
|
|
917
|
-
}
|
|
892
|
+
_ctx.fill()
|
|
918
893
|
},
|
|
919
894
|
|
|
920
895
|
/**
|
|
921
|
-
* Outlines the current
|
|
896
|
+
* Outlines the current path with a given color.
|
|
922
897
|
*
|
|
923
898
|
* @param {number} [color=0]
|
|
924
|
-
* @param {Path2D} [path]
|
|
925
899
|
*/
|
|
926
|
-
stroke(color
|
|
900
|
+
stroke(color) {
|
|
927
901
|
DEV: assert(
|
|
928
902
|
null == color || (isNumber(color) && color >= 0),
|
|
929
903
|
'[litecanvas] stroke() 1st param must be a positive number or zero'
|
|
930
904
|
)
|
|
931
|
-
DEV: assert(
|
|
932
|
-
null == path || path instanceof Path2D,
|
|
933
|
-
'[litecanvas] stroke() 2nd param must be a Path2D instance'
|
|
934
|
-
)
|
|
935
905
|
|
|
936
906
|
_ctx.strokeStyle = _colors[~~color % _colors.length]
|
|
937
|
-
|
|
938
|
-
_ctx.stroke(path)
|
|
939
|
-
} else {
|
|
940
|
-
_ctx.stroke()
|
|
941
|
-
}
|
|
907
|
+
_ctx.stroke()
|
|
942
908
|
},
|
|
943
909
|
|
|
944
910
|
/**
|
|
945
|
-
*
|
|
911
|
+
* Turns a path (in the callback) into the current clipping region.
|
|
946
912
|
*
|
|
947
|
-
*
|
|
948
|
-
*
|
|
949
|
-
* @param {Path2D} path
|
|
913
|
+
* @param {clipCallback} callback
|
|
950
914
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clip
|
|
951
915
|
*/
|
|
952
|
-
clip(
|
|
916
|
+
clip(callback) {
|
|
953
917
|
DEV: assert(
|
|
954
|
-
|
|
955
|
-
'[litecanvas] clip() 1st param must be a
|
|
918
|
+
'function' === typeof callback,
|
|
919
|
+
'[litecanvas] clip() 1st param must be a function'
|
|
956
920
|
)
|
|
957
921
|
|
|
958
|
-
_ctx
|
|
922
|
+
beginPath(_ctx)
|
|
923
|
+
callback(_ctx)
|
|
924
|
+
_ctx.clip()
|
|
959
925
|
},
|
|
960
926
|
|
|
961
927
|
/** SOUND API */
|
|
@@ -1020,6 +986,7 @@ export default function litecanvas(settings = {}) {
|
|
|
1020
986
|
* @returns {HTMLCanvasElement}
|
|
1021
987
|
*/
|
|
1022
988
|
canvas: () => _canvas,
|
|
989
|
+
|
|
1023
990
|
/**
|
|
1024
991
|
* Prepares a plugin to be loaded
|
|
1025
992
|
*
|
|
@@ -1169,7 +1136,7 @@ export default function litecanvas(settings = {}) {
|
|
|
1169
1136
|
// 1
|
|
1170
1137
|
_initialized,
|
|
1171
1138
|
// 2
|
|
1172
|
-
|
|
1139
|
+
_deltaTime,
|
|
1173
1140
|
// 3
|
|
1174
1141
|
_scale,
|
|
1175
1142
|
// 4
|
|
@@ -1204,9 +1171,7 @@ export default function litecanvas(settings = {}) {
|
|
|
1204
1171
|
*/
|
|
1205
1172
|
quit() {
|
|
1206
1173
|
// stop the game loop (update & draw)
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
_rafid = 0
|
|
1174
|
+
instance.pause()
|
|
1210
1175
|
|
|
1211
1176
|
// emit "quit" event to manual clean ups
|
|
1212
1177
|
instance.emit('quit')
|
|
@@ -1231,6 +1196,32 @@ export default function litecanvas(settings = {}) {
|
|
|
1231
1196
|
// unset that flag
|
|
1232
1197
|
_initialized = false
|
|
1233
1198
|
},
|
|
1199
|
+
|
|
1200
|
+
/**
|
|
1201
|
+
* Pauses the engine loop (update & draw).
|
|
1202
|
+
*/
|
|
1203
|
+
pause() {
|
|
1204
|
+
cancelAnimationFrame(_rafid)
|
|
1205
|
+
_rafid = 0
|
|
1206
|
+
},
|
|
1207
|
+
|
|
1208
|
+
/**
|
|
1209
|
+
* Resumes (if paused) the engine loop.
|
|
1210
|
+
*/
|
|
1211
|
+
resume() {
|
|
1212
|
+
if (!_rafid && _initialized) {
|
|
1213
|
+
_rafid = raf(drawFrame)
|
|
1214
|
+
}
|
|
1215
|
+
},
|
|
1216
|
+
|
|
1217
|
+
/**
|
|
1218
|
+
* Returns `true` if the engine loop is paused.
|
|
1219
|
+
*
|
|
1220
|
+
* @returns {boolean}
|
|
1221
|
+
*/
|
|
1222
|
+
paused() {
|
|
1223
|
+
return !_rafid
|
|
1224
|
+
},
|
|
1234
1225
|
}
|
|
1235
1226
|
|
|
1236
1227
|
// prettier-ignore
|
|
@@ -1506,51 +1497,49 @@ export default function litecanvas(settings = {}) {
|
|
|
1506
1497
|
)
|
|
1507
1498
|
}
|
|
1508
1499
|
|
|
1500
|
+
// start the engine
|
|
1509
1501
|
_initialized = true
|
|
1510
|
-
|
|
1511
|
-
// start the game loop
|
|
1512
1502
|
instance.emit('init', instance)
|
|
1513
1503
|
|
|
1504
|
+
// set the default text align and baseline
|
|
1505
|
+
instance.textalign('start', 'top')
|
|
1506
|
+
|
|
1514
1507
|
_lastFrameTime = performance.now()
|
|
1515
|
-
|
|
1508
|
+
instance.resume()
|
|
1516
1509
|
}
|
|
1517
1510
|
|
|
1518
1511
|
/**
|
|
1519
1512
|
* @param {DOMHighResTimeStamp} now
|
|
1520
1513
|
*/
|
|
1521
1514
|
function drawFrame(now) {
|
|
1515
|
+
if (!settings.animate) {
|
|
1516
|
+
return instance.emit('draw')
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1522
1519
|
let updated = 0
|
|
1520
|
+
let frameTime = (now - _lastFrameTime) / 1000
|
|
1523
1521
|
|
|
1524
|
-
|
|
1525
|
-
// prevents too long frames
|
|
1526
|
-
_accumulated += math.min(0.1, (now - _lastFrameTime) / 1000)
|
|
1527
|
-
_lastFrameTime = now
|
|
1522
|
+
_lastFrameTime = now
|
|
1528
1523
|
|
|
1524
|
+
if (frameTime < 0.1) {
|
|
1525
|
+
_accumulated += frameTime
|
|
1529
1526
|
while (_accumulated >= _deltaTime) {
|
|
1530
1527
|
updated++
|
|
1531
1528
|
instance.emit('update', _deltaTime * _timeScale, updated)
|
|
1532
1529
|
instance.def('T', instance.T + _deltaTime * _timeScale)
|
|
1533
1530
|
_accumulated -= _deltaTime
|
|
1534
1531
|
}
|
|
1535
|
-
|
|
1536
|
-
// request the next frame
|
|
1537
|
-
// check if the last ID exists, because
|
|
1538
|
-
// quit() delete it (sets to zero)
|
|
1539
|
-
if (_rafid) {
|
|
1540
|
-
_rafid = raf(drawFrame)
|
|
1541
|
-
}
|
|
1542
|
-
} else {
|
|
1543
|
-
// when the canvas is not animated
|
|
1544
|
-
// we force one frame when redraws are triggered
|
|
1545
|
-
updated = 1
|
|
1546
1532
|
}
|
|
1547
1533
|
|
|
1548
1534
|
if (updated) {
|
|
1549
|
-
// always set default values for
|
|
1550
|
-
// _ctx.textAlign and _ctx.textBaseline before draw
|
|
1551
|
-
instance.textalign('start', 'top')
|
|
1552
1535
|
instance.emit('draw')
|
|
1553
1536
|
}
|
|
1537
|
+
|
|
1538
|
+
// request the next frame
|
|
1539
|
+
// only when the engine loop are not paused (_rafid >= 1)
|
|
1540
|
+
if (_rafid) {
|
|
1541
|
+
_rafid = raf(drawFrame)
|
|
1542
|
+
}
|
|
1554
1543
|
}
|
|
1555
1544
|
|
|
1556
1545
|
function setupCanvas() {
|
package/types/index.d.ts
CHANGED
|
@@ -444,35 +444,24 @@ declare global {
|
|
|
444
444
|
*/
|
|
445
445
|
function alpha(value: number): void
|
|
446
446
|
/**
|
|
447
|
-
*
|
|
448
|
-
* path as an argument (creates a copy), or optionally with a string
|
|
449
|
-
* consisting of SVG path data.
|
|
450
|
-
*
|
|
451
|
-
* @param [arg]
|
|
452
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/API/Path2D/Path2D
|
|
453
|
-
*/
|
|
454
|
-
function path(arg?: Path2D | string): Path2D
|
|
455
|
-
/**
|
|
456
|
-
* Fills the current or given path with a given color.
|
|
447
|
+
* Fills the current path with a given color.
|
|
457
448
|
*
|
|
458
449
|
* @param color
|
|
459
|
-
* @param [path]
|
|
460
450
|
*/
|
|
461
|
-
function fill(color: number
|
|
451
|
+
function fill(color: number): void
|
|
462
452
|
/**
|
|
463
|
-
* Outlines the current
|
|
453
|
+
* Outlines the current path with a given color.
|
|
464
454
|
*
|
|
465
455
|
* @param color
|
|
466
|
-
* @param [path]
|
|
467
456
|
*/
|
|
468
|
-
function stroke(color: number
|
|
457
|
+
function stroke(color: number): void
|
|
469
458
|
/**
|
|
470
|
-
*
|
|
459
|
+
* Turns a path (in the callback) into the current clipping region.
|
|
471
460
|
*
|
|
472
|
-
* @param
|
|
461
|
+
* @param callback
|
|
473
462
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clip
|
|
474
463
|
*/
|
|
475
|
-
function clip(
|
|
464
|
+
function clip(callback: clipCallback): void
|
|
476
465
|
|
|
477
466
|
/** SOUND API */
|
|
478
467
|
/**
|
|
@@ -578,7 +567,7 @@ declare global {
|
|
|
578
567
|
*
|
|
579
568
|
* - n = 0: the settings passed to that instance
|
|
580
569
|
* - n = 1: returns true if the "init" event has already been emitted
|
|
581
|
-
* - n = 2: the current
|
|
570
|
+
* - n = 2: the current delta time (dt)
|
|
582
571
|
* - n = 3: the current canvas element scale (not the context 2D scale)
|
|
583
572
|
* - n = 4: the attached event callbacks
|
|
584
573
|
* - n = 5: the current color palette
|
|
@@ -588,13 +577,25 @@ declare global {
|
|
|
588
577
|
* - n = 9: the current RNG state
|
|
589
578
|
* - n = 10: the current font size
|
|
590
579
|
* - n = 11: the current font family
|
|
591
|
-
* - n = *any other value*: returns undefined
|
|
580
|
+
* - n = *any other value*: probably returns undefined
|
|
592
581
|
*
|
|
593
582
|
* @param n
|
|
594
583
|
*/
|
|
595
584
|
function stat(n: number): any
|
|
596
585
|
/**
|
|
597
|
-
*
|
|
586
|
+
* Shutdown the litecanvas instance and remove all event listeners.
|
|
598
587
|
*/
|
|
599
588
|
function quit(): void
|
|
589
|
+
/**
|
|
590
|
+
* Pauses the engine loop (update & draw).
|
|
591
|
+
*/
|
|
592
|
+
function pause(): void
|
|
593
|
+
/**
|
|
594
|
+
* Resumes (if paused) the engine loop.
|
|
595
|
+
*/
|
|
596
|
+
function resume(): void
|
|
597
|
+
/**
|
|
598
|
+
* Returns `true` if the engine loop is paused.
|
|
599
|
+
*/
|
|
600
|
+
function paused(): boolean
|
|
600
601
|
}
|
package/types/types.d.ts
CHANGED
|
@@ -435,35 +435,24 @@ type LitecanvasInstance = {
|
|
|
435
435
|
*/
|
|
436
436
|
alpha(value: number): void
|
|
437
437
|
/**
|
|
438
|
-
*
|
|
439
|
-
* path as an argument (creates a copy), or optionally with a string
|
|
440
|
-
* consisting of SVG path data.
|
|
441
|
-
*
|
|
442
|
-
* @param [arg]
|
|
443
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/API/Path2D/Path2D
|
|
444
|
-
*/
|
|
445
|
-
path(arg?: Path2D | string): Path2D
|
|
446
|
-
/**
|
|
447
|
-
* Fills the current or given path with a given color.
|
|
438
|
+
* Fills the current path with a given color.
|
|
448
439
|
*
|
|
449
440
|
* @param color
|
|
450
|
-
* @param [path]
|
|
451
441
|
*/
|
|
452
|
-
fill(color: number
|
|
442
|
+
fill(color: number): void
|
|
453
443
|
/**
|
|
454
|
-
* Outlines the current
|
|
444
|
+
* Outlines the current path with a given color.
|
|
455
445
|
*
|
|
456
446
|
* @param color
|
|
457
|
-
* @param [path]
|
|
458
447
|
*/
|
|
459
|
-
stroke(color: number
|
|
448
|
+
stroke(color: number): void
|
|
460
449
|
/**
|
|
461
|
-
*
|
|
450
|
+
* Turns a path (in the callback) into the current clipping region.
|
|
462
451
|
*
|
|
463
|
-
* @param
|
|
452
|
+
* @param callback
|
|
464
453
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clip
|
|
465
454
|
*/
|
|
466
|
-
clip(
|
|
455
|
+
clip(callback: clipCallback): void
|
|
467
456
|
|
|
468
457
|
/** SOUND API */
|
|
469
458
|
/**
|
|
@@ -565,7 +554,7 @@ type LitecanvasInstance = {
|
|
|
565
554
|
*
|
|
566
555
|
* - n = 0: the settings passed to that instance
|
|
567
556
|
* - n = 1: returns true if the "init" event has already been emitted
|
|
568
|
-
* - n = 2: the current
|
|
557
|
+
* - n = 2: the current delta time (dt)
|
|
569
558
|
* - n = 3: the current canvas element scale (not the context 2D scale)
|
|
570
559
|
* - n = 4: the attached event callbacks
|
|
571
560
|
* - n = 5: the current color palette
|
|
@@ -575,7 +564,7 @@ type LitecanvasInstance = {
|
|
|
575
564
|
* - n = 9: the current RNG state
|
|
576
565
|
* - n = 10: the current font size
|
|
577
566
|
* - n = 11: the current font family
|
|
578
|
-
* - n = *any other value*: returns undefined
|
|
567
|
+
* - n = *any other value*: probably returns undefined
|
|
579
568
|
*
|
|
580
569
|
* @param n
|
|
581
570
|
*/
|
|
@@ -584,6 +573,18 @@ type LitecanvasInstance = {
|
|
|
584
573
|
* Stops the litecanvas instance and remove all event listeners.
|
|
585
574
|
*/
|
|
586
575
|
quit(): void
|
|
576
|
+
/**
|
|
577
|
+
* Pauses the engine loop (update & draw).
|
|
578
|
+
*/
|
|
579
|
+
pause(): void
|
|
580
|
+
/**
|
|
581
|
+
* Resumes (if paused) the engine loop.
|
|
582
|
+
*/
|
|
583
|
+
resume(): void
|
|
584
|
+
/**
|
|
585
|
+
* Returns `true` if the engine loop is paused.
|
|
586
|
+
*/
|
|
587
|
+
paused(): boolean
|
|
587
588
|
}
|
|
588
589
|
|
|
589
590
|
type LitecanvasOptions = {
|
|
@@ -667,3 +668,5 @@ type LitecanvasGameLoop = {
|
|
|
667
668
|
type drawCallback = (context: OffscreenCanvasRenderingContext2D) => void
|
|
668
669
|
|
|
669
670
|
type pluginCallback = (instance: LitecanvasInstance, config?: any) => any
|
|
671
|
+
|
|
672
|
+
type clipCallback = (ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D) => void
|