graphico 1.0.0 → 1.1.1
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 +17 -8
- package/dist/canvas.js +127 -8
- package/package.json +7 -2
- package/types/canvas.d.ts +38 -1
- package/types/types.d.ts +8 -0
package/README.md
CHANGED
|
@@ -4,11 +4,20 @@
|
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
`graphico` boasts several features that make it an extremely versatile package for several project types.
|
|
8
|
+
|
|
9
|
+
- Simple, **object-oriented canvas API** for organized graphics programming
|
|
10
|
+
- Easy debugging and extensive configuration for **complete customizability**
|
|
11
|
+
- Supports multiple independent **canvas layers** with transparency
|
|
12
|
+
- **Hardware-accelerated graphics** for fast and smooth animation
|
|
13
|
+
- **User interaction** captured via keyboard inputs or mouse movements or clicks
|
|
14
|
+
- Multiple audio tracks supported by system **audio player** with volume, mute, and loop toggle
|
|
15
|
+
- Built-in logic for **screenshots** and **screen recordings** that capture both video and audio
|
|
16
|
+
|
|
17
|
+
## Caveats
|
|
18
|
+
|
|
19
|
+
By default, many browsers prevent autoplay, which arguably is a good thing. (Don't you hate it when you have several tabs open and one of them starts making noise?) This security feature blocks API calls to `Canvas.playAudio()` from being called automatically on page load. It needs to be triggered manually (initially) by some form of user interaction; either a key press or a mouse click. After this initial interaction step, calls to `playAudio()` can be performed automatically. If you wanted to have background music looping for a game, it would need to be triggered after pressing the "start" button, for example.
|
|
20
|
+
|
|
21
|
+
## Learn More
|
|
22
|
+
|
|
23
|
+
The best way to learn and experience its features is to try it out yourself. See the examples to learn how to use `graphico`!
|
package/dist/canvas.js
CHANGED
|
@@ -44,6 +44,18 @@ var Canvas = /** @class */ (function () {
|
|
|
44
44
|
* Determine whether the client is focused or not
|
|
45
45
|
*/
|
|
46
46
|
this.focused = false;
|
|
47
|
+
/**
|
|
48
|
+
* Determine whether the user has interacted with this canvas
|
|
49
|
+
*/
|
|
50
|
+
this.interacted = false;
|
|
51
|
+
/**
|
|
52
|
+
* Determine whether audio is allowed or muted
|
|
53
|
+
*/
|
|
54
|
+
this.muted = false;
|
|
55
|
+
/**
|
|
56
|
+
* Contains the list of all active audio elements
|
|
57
|
+
*/
|
|
58
|
+
this.audios = [];
|
|
47
59
|
this.config = Canvas.setDefaults(options, Canvas.defaults);
|
|
48
60
|
this.width = this.config.width;
|
|
49
61
|
this.height = this.config.height;
|
|
@@ -95,6 +107,8 @@ var Canvas = /** @class */ (function () {
|
|
|
95
107
|
_this.config.mousemove(_this.mouseX, _this.mouseY);
|
|
96
108
|
});
|
|
97
109
|
main.addEventListener('keydown', function (e) {
|
|
110
|
+
audioContext.resume();
|
|
111
|
+
_this.interacted = true;
|
|
98
112
|
if (!_this.focused) {
|
|
99
113
|
return;
|
|
100
114
|
}
|
|
@@ -119,6 +133,8 @@ var Canvas = /** @class */ (function () {
|
|
|
119
133
|
}
|
|
120
134
|
});
|
|
121
135
|
main.addEventListener('mousedown', function (e) {
|
|
136
|
+
audioContext.resume();
|
|
137
|
+
_this.interacted = true;
|
|
122
138
|
if (!_this.focused) {
|
|
123
139
|
return;
|
|
124
140
|
}
|
|
@@ -148,21 +164,40 @@ var Canvas = /** @class */ (function () {
|
|
|
148
164
|
_this.animation = requestAnimationFrame(function (time) { return _this.startAnimate(time); });
|
|
149
165
|
});
|
|
150
166
|
main.addEventListener('focusout', function (e) {
|
|
151
|
-
_this.
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
167
|
+
if (_this.config.keepFocused) {
|
|
168
|
+
main.focus();
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
_this.focused = false;
|
|
172
|
+
main.style.borderColor = _this.config.borderBlur;
|
|
173
|
+
_this.log(e.type, _this.focused);
|
|
174
|
+
cancelAnimationFrame(_this.animation);
|
|
175
|
+
}
|
|
155
176
|
});
|
|
156
177
|
window.addEventListener('blur', function (e) {
|
|
157
178
|
_this.log(e.type);
|
|
158
179
|
cancelAnimationFrame(_this.animation);
|
|
159
180
|
});
|
|
160
181
|
main.addEventListener('contextmenu', function (e) { return e.preventDefault(); });
|
|
161
|
-
//
|
|
162
|
-
main.
|
|
182
|
+
// Initialize audio tracks for recording
|
|
183
|
+
var stream = new MediaStream(main.captureStream()); // video stream
|
|
184
|
+
var audioContext = new window.AudioContext();
|
|
185
|
+
for (var track = 0; track < this.config.numTracks; track++) {
|
|
186
|
+
var audio = new Audio();
|
|
187
|
+
var source = audioContext.createMediaElementSource(audio);
|
|
188
|
+
var destination = audioContext.createMediaStreamDestination();
|
|
189
|
+
source.connect(destination); // contains the audio stream for recording
|
|
190
|
+
source.connect(audioContext.destination); // so the user can hear
|
|
191
|
+
this.audios.push(audio);
|
|
192
|
+
for (var _i = 0, _a = destination.stream.getAudioTracks(); _i < _a.length; _i++) {
|
|
193
|
+
var audioTrack = _a[_i];
|
|
194
|
+
this.log("Adding ".concat(audioTrack.id, " to track ").concat(track, "."));
|
|
195
|
+
stream.addTrack(audioTrack); // add audio track
|
|
196
|
+
}
|
|
197
|
+
}
|
|
163
198
|
// Initialize the media recorder
|
|
164
199
|
var recordPart = [];
|
|
165
|
-
this.recorder = new MediaRecorder(
|
|
200
|
+
this.recorder = new MediaRecorder(stream);
|
|
166
201
|
this.recorder.addEventListener('dataavailable', function (e) {
|
|
167
202
|
_this.log(e.type);
|
|
168
203
|
recordPart.push(e.data);
|
|
@@ -181,6 +216,8 @@ var Canvas = /** @class */ (function () {
|
|
|
181
216
|
_this.keys.splice(0);
|
|
182
217
|
_this.mouseButtons.splice(0);
|
|
183
218
|
});
|
|
219
|
+
// Focus on the canvas
|
|
220
|
+
main.focus();
|
|
184
221
|
}
|
|
185
222
|
/**
|
|
186
223
|
* Start the animation.
|
|
@@ -252,6 +289,9 @@ var Canvas = /** @class */ (function () {
|
|
|
252
289
|
* Start recording all layers on the canvas
|
|
253
290
|
*/
|
|
254
291
|
Canvas.prototype.startRecording = function () {
|
|
292
|
+
if (!this.interacted) {
|
|
293
|
+
throw new Error('The user has not yet interacted with this canvas.');
|
|
294
|
+
}
|
|
255
295
|
this.recorder.start();
|
|
256
296
|
};
|
|
257
297
|
/**
|
|
@@ -262,11 +302,82 @@ var Canvas = /** @class */ (function () {
|
|
|
262
302
|
};
|
|
263
303
|
/**
|
|
264
304
|
* Determines whether the media recorder is active
|
|
265
|
-
* @returns
|
|
305
|
+
* @returns True if currently recording
|
|
266
306
|
*/
|
|
267
307
|
Canvas.prototype.isRecording = function () {
|
|
268
308
|
return this.recorder.state === 'recording';
|
|
269
309
|
};
|
|
310
|
+
/**
|
|
311
|
+
* Play an audio file
|
|
312
|
+
* @param src The path of the audio file
|
|
313
|
+
* @param loop Whether to play the audio on loop
|
|
314
|
+
* @param volume The normalized [0-1] volume
|
|
315
|
+
* @param track The track number to play on
|
|
316
|
+
*/
|
|
317
|
+
Canvas.prototype.playAudio = function (src, loop, volume, track) {
|
|
318
|
+
if (loop === void 0) { loop = false; }
|
|
319
|
+
if (volume === void 0) { volume = 1; }
|
|
320
|
+
if (track === void 0) { track = 0; }
|
|
321
|
+
this.log("Playing audio on track ".concat(track, "."));
|
|
322
|
+
if (!this.interacted) {
|
|
323
|
+
throw new Error('The user has not yet interacted with this canvas.');
|
|
324
|
+
}
|
|
325
|
+
if (track < 0 || track >= this.config.numTracks) {
|
|
326
|
+
throw new Error("Track ".concat(track, " is out of range. [0,").concat(this.config.numTracks, ")"));
|
|
327
|
+
}
|
|
328
|
+
var audio = this.audios[track];
|
|
329
|
+
audio.src = src;
|
|
330
|
+
audio.loop = loop;
|
|
331
|
+
audio.volume = volume;
|
|
332
|
+
audio.muted = this.muted;
|
|
333
|
+
audio.play();
|
|
334
|
+
};
|
|
335
|
+
/**
|
|
336
|
+
* Stop all audio tracks from playing
|
|
337
|
+
*/
|
|
338
|
+
Canvas.prototype.stopAudio = function (track) {
|
|
339
|
+
if (track === void 0) { track = -1; }
|
|
340
|
+
this.log("Stopping audio on track ".concat(track, "."));
|
|
341
|
+
if (track >= this.config.numTracks) {
|
|
342
|
+
throw new Error("Track ".concat(track, " is out of range. [0,").concat(this.config.numTracks, ")"));
|
|
343
|
+
}
|
|
344
|
+
if (track < 0) {
|
|
345
|
+
for (var _i = 0, _a = this.audios; _i < _a.length; _i++) {
|
|
346
|
+
var audio = _a[_i];
|
|
347
|
+
audio.pause();
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
this.audios[track].pause();
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
/**
|
|
355
|
+
* Mute all audio
|
|
356
|
+
*/
|
|
357
|
+
Canvas.prototype.mute = function () {
|
|
358
|
+
this.muted = true;
|
|
359
|
+
for (var _i = 0, _a = this.audios; _i < _a.length; _i++) {
|
|
360
|
+
var audio = _a[_i];
|
|
361
|
+
audio.muted = this.muted;
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
/**
|
|
365
|
+
* Unmute all audio
|
|
366
|
+
*/
|
|
367
|
+
Canvas.prototype.unmute = function () {
|
|
368
|
+
this.muted = false;
|
|
369
|
+
for (var _i = 0, _a = this.audios; _i < _a.length; _i++) {
|
|
370
|
+
var audio = _a[_i];
|
|
371
|
+
audio.muted = this.muted;
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
/**
|
|
375
|
+
* Determines whether audio is muted
|
|
376
|
+
* @returns True if currently muted
|
|
377
|
+
*/
|
|
378
|
+
Canvas.prototype.isMuted = function () {
|
|
379
|
+
return this.muted;
|
|
380
|
+
};
|
|
270
381
|
/**
|
|
271
382
|
* Draw an object onto the canvas.
|
|
272
383
|
* @param drawable Any drawable object
|
|
@@ -274,6 +385,9 @@ var Canvas = /** @class */ (function () {
|
|
|
274
385
|
*/
|
|
275
386
|
Canvas.prototype.draw = function (drawable, layer) {
|
|
276
387
|
if (layer === void 0) { layer = 0; }
|
|
388
|
+
if (layer < 0 || layer >= this.config.numLayers) {
|
|
389
|
+
throw new Error("Layer ".concat(layer, " is out of range. [0,").concat(this.config.numLayers, ")"));
|
|
390
|
+
}
|
|
277
391
|
drawable.draw(this.layers[layer]);
|
|
278
392
|
};
|
|
279
393
|
/**
|
|
@@ -282,6 +396,9 @@ var Canvas = /** @class */ (function () {
|
|
|
282
396
|
*/
|
|
283
397
|
Canvas.prototype.clear = function (layer) {
|
|
284
398
|
if (layer === void 0) { layer = -1; }
|
|
399
|
+
if (layer >= this.config.numLayers) {
|
|
400
|
+
throw new Error("Layer ".concat(layer, " is out of range. [0,").concat(this.config.numLayers, ")"));
|
|
401
|
+
}
|
|
285
402
|
if (layer < 0) {
|
|
286
403
|
for (var _i = 0, _a = this.layers; _i < _a.length; _i++) {
|
|
287
404
|
var layer_1 = _a[_i];
|
|
@@ -329,7 +446,9 @@ var Canvas = /** @class */ (function () {
|
|
|
329
446
|
border: 'transparent',
|
|
330
447
|
borderBlur: 'transparent',
|
|
331
448
|
showMouse: true,
|
|
449
|
+
keepFocused: false,
|
|
332
450
|
numLayers: 1,
|
|
451
|
+
numTracks: 1,
|
|
333
452
|
keydown: function () { return; },
|
|
334
453
|
keyup: function () { return; },
|
|
335
454
|
mousemove: function () { return; },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "graphico",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Canvas 2D rendering toolkit for games and visual projects",
|
|
5
5
|
"homepage": "https://npm.nicfv.com/",
|
|
6
6
|
"bin": "",
|
|
@@ -23,7 +23,12 @@
|
|
|
23
23
|
"drawing",
|
|
24
24
|
"art",
|
|
25
25
|
"render",
|
|
26
|
-
"2D"
|
|
26
|
+
"2D",
|
|
27
|
+
"layer",
|
|
28
|
+
"audio",
|
|
29
|
+
"track",
|
|
30
|
+
"animate",
|
|
31
|
+
"visual"
|
|
27
32
|
],
|
|
28
33
|
"author": {
|
|
29
34
|
"name": "Nicolas Ventura",
|
package/types/canvas.d.ts
CHANGED
|
@@ -55,10 +55,22 @@ export declare class Canvas {
|
|
|
55
55
|
* Determine whether the client is focused or not
|
|
56
56
|
*/
|
|
57
57
|
private focused;
|
|
58
|
+
/**
|
|
59
|
+
* Determine whether the user has interacted with this canvas
|
|
60
|
+
*/
|
|
61
|
+
private interacted;
|
|
58
62
|
/**
|
|
59
63
|
* The media recording object for screen captures
|
|
60
64
|
*/
|
|
61
65
|
private readonly recorder;
|
|
66
|
+
/**
|
|
67
|
+
* Determine whether audio is allowed or muted
|
|
68
|
+
*/
|
|
69
|
+
private muted;
|
|
70
|
+
/**
|
|
71
|
+
* Contains the list of all active audio elements
|
|
72
|
+
*/
|
|
73
|
+
private readonly audios;
|
|
62
74
|
/**
|
|
63
75
|
* Create a new canvas with the provided options
|
|
64
76
|
* @param options Configuration options
|
|
@@ -104,9 +116,34 @@ export declare class Canvas {
|
|
|
104
116
|
stopRecording(): void;
|
|
105
117
|
/**
|
|
106
118
|
* Determines whether the media recorder is active
|
|
107
|
-
* @returns
|
|
119
|
+
* @returns True if currently recording
|
|
108
120
|
*/
|
|
109
121
|
isRecording(): boolean;
|
|
122
|
+
/**
|
|
123
|
+
* Play an audio file
|
|
124
|
+
* @param src The path of the audio file
|
|
125
|
+
* @param loop Whether to play the audio on loop
|
|
126
|
+
* @param volume The normalized [0-1] volume
|
|
127
|
+
* @param track The track number to play on
|
|
128
|
+
*/
|
|
129
|
+
playAudio(src: string, loop?: boolean, volume?: number, track?: number): void;
|
|
130
|
+
/**
|
|
131
|
+
* Stop all audio tracks from playing
|
|
132
|
+
*/
|
|
133
|
+
stopAudio(track?: number): void;
|
|
134
|
+
/**
|
|
135
|
+
* Mute all audio
|
|
136
|
+
*/
|
|
137
|
+
mute(): void;
|
|
138
|
+
/**
|
|
139
|
+
* Unmute all audio
|
|
140
|
+
*/
|
|
141
|
+
unmute(): void;
|
|
142
|
+
/**
|
|
143
|
+
* Determines whether audio is muted
|
|
144
|
+
* @returns True if currently muted
|
|
145
|
+
*/
|
|
146
|
+
isMuted(): boolean;
|
|
110
147
|
/**
|
|
111
148
|
* Draw an object onto the canvas.
|
|
112
149
|
* @param drawable Any drawable object
|
package/types/types.d.ts
CHANGED
|
@@ -38,10 +38,18 @@ export interface Options {
|
|
|
38
38
|
* Optionally show or hide the mouse when hovering over the canvas
|
|
39
39
|
*/
|
|
40
40
|
readonly showMouse: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Refocus the canvas when it loses focus
|
|
43
|
+
*/
|
|
44
|
+
readonly keepFocused: boolean;
|
|
41
45
|
/**
|
|
42
46
|
* The number of layers in this canvas
|
|
43
47
|
*/
|
|
44
48
|
readonly numLayers: number;
|
|
49
|
+
/**
|
|
50
|
+
* The number of audio tracks
|
|
51
|
+
*/
|
|
52
|
+
readonly numTracks: number;
|
|
45
53
|
/**
|
|
46
54
|
* Event listener for when a key is pressed
|
|
47
55
|
* @param key The key that was pressed
|