graphico 1.0.0 → 1.1.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 +17 -8
- package/dist/canvas.js +117 -4
- package/package.json +7 -2
- package/types/canvas.d.ts +38 -1
- package/types/types.d.ts +4 -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
|
}
|
|
@@ -158,11 +174,25 @@ var Canvas = /** @class */ (function () {
|
|
|
158
174
|
cancelAnimationFrame(_this.animation);
|
|
159
175
|
});
|
|
160
176
|
main.addEventListener('contextmenu', function (e) { return e.preventDefault(); });
|
|
161
|
-
//
|
|
162
|
-
main.
|
|
177
|
+
// Initialize audio tracks for recording
|
|
178
|
+
var stream = new MediaStream(main.captureStream()); // video stream
|
|
179
|
+
var audioContext = new window.AudioContext();
|
|
180
|
+
for (var track = 0; track < this.config.numTracks; track++) {
|
|
181
|
+
var audio = new Audio();
|
|
182
|
+
var source = audioContext.createMediaElementSource(audio);
|
|
183
|
+
var destination = audioContext.createMediaStreamDestination();
|
|
184
|
+
source.connect(destination); // contains the audio stream for recording
|
|
185
|
+
source.connect(audioContext.destination); // so the user can hear
|
|
186
|
+
this.audios.push(audio);
|
|
187
|
+
for (var _i = 0, _a = destination.stream.getAudioTracks(); _i < _a.length; _i++) {
|
|
188
|
+
var audioTrack = _a[_i];
|
|
189
|
+
this.log("Adding ".concat(audioTrack.id, " to track ").concat(track, "."));
|
|
190
|
+
stream.addTrack(audioTrack); // add audio track
|
|
191
|
+
}
|
|
192
|
+
}
|
|
163
193
|
// Initialize the media recorder
|
|
164
194
|
var recordPart = [];
|
|
165
|
-
this.recorder = new MediaRecorder(
|
|
195
|
+
this.recorder = new MediaRecorder(stream);
|
|
166
196
|
this.recorder.addEventListener('dataavailable', function (e) {
|
|
167
197
|
_this.log(e.type);
|
|
168
198
|
recordPart.push(e.data);
|
|
@@ -181,6 +211,8 @@ var Canvas = /** @class */ (function () {
|
|
|
181
211
|
_this.keys.splice(0);
|
|
182
212
|
_this.mouseButtons.splice(0);
|
|
183
213
|
});
|
|
214
|
+
// Focus on the canvas
|
|
215
|
+
main.focus();
|
|
184
216
|
}
|
|
185
217
|
/**
|
|
186
218
|
* Start the animation.
|
|
@@ -252,6 +284,9 @@ var Canvas = /** @class */ (function () {
|
|
|
252
284
|
* Start recording all layers on the canvas
|
|
253
285
|
*/
|
|
254
286
|
Canvas.prototype.startRecording = function () {
|
|
287
|
+
if (!this.interacted) {
|
|
288
|
+
throw new Error('The user has not yet interacted with this canvas.');
|
|
289
|
+
}
|
|
255
290
|
this.recorder.start();
|
|
256
291
|
};
|
|
257
292
|
/**
|
|
@@ -262,11 +297,82 @@ var Canvas = /** @class */ (function () {
|
|
|
262
297
|
};
|
|
263
298
|
/**
|
|
264
299
|
* Determines whether the media recorder is active
|
|
265
|
-
* @returns
|
|
300
|
+
* @returns True if currently recording
|
|
266
301
|
*/
|
|
267
302
|
Canvas.prototype.isRecording = function () {
|
|
268
303
|
return this.recorder.state === 'recording';
|
|
269
304
|
};
|
|
305
|
+
/**
|
|
306
|
+
* Play an audio file
|
|
307
|
+
* @param src The path of the audio file
|
|
308
|
+
* @param loop Whether to play the audio on loop
|
|
309
|
+
* @param volume The normalized [0-1] volume
|
|
310
|
+
* @param track The track number to play on
|
|
311
|
+
*/
|
|
312
|
+
Canvas.prototype.playAudio = function (src, loop, volume, track) {
|
|
313
|
+
if (loop === void 0) { loop = false; }
|
|
314
|
+
if (volume === void 0) { volume = 1; }
|
|
315
|
+
if (track === void 0) { track = 0; }
|
|
316
|
+
this.log("Playing audio on track ".concat(track, "."));
|
|
317
|
+
if (!this.interacted) {
|
|
318
|
+
throw new Error('The user has not yet interacted with this canvas.');
|
|
319
|
+
}
|
|
320
|
+
if (track < 0 || track >= this.config.numTracks) {
|
|
321
|
+
throw new Error("Track ".concat(track, " is out of range. [0,").concat(this.config.numTracks, ")"));
|
|
322
|
+
}
|
|
323
|
+
var audio = this.audios[track];
|
|
324
|
+
audio.src = src;
|
|
325
|
+
audio.loop = loop;
|
|
326
|
+
audio.volume = volume;
|
|
327
|
+
audio.muted = this.muted;
|
|
328
|
+
audio.play();
|
|
329
|
+
};
|
|
330
|
+
/**
|
|
331
|
+
* Stop all audio tracks from playing
|
|
332
|
+
*/
|
|
333
|
+
Canvas.prototype.stopAudio = function (track) {
|
|
334
|
+
if (track === void 0) { track = -1; }
|
|
335
|
+
this.log("Stopping audio on track ".concat(track, "."));
|
|
336
|
+
if (track >= this.config.numTracks) {
|
|
337
|
+
throw new Error("Track ".concat(track, " is out of range. [0,").concat(this.config.numTracks, ")"));
|
|
338
|
+
}
|
|
339
|
+
if (track < 0) {
|
|
340
|
+
for (var _i = 0, _a = this.audios; _i < _a.length; _i++) {
|
|
341
|
+
var audio = _a[_i];
|
|
342
|
+
audio.pause();
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
this.audios[track].pause();
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
/**
|
|
350
|
+
* Mute all audio
|
|
351
|
+
*/
|
|
352
|
+
Canvas.prototype.mute = function () {
|
|
353
|
+
this.muted = true;
|
|
354
|
+
for (var _i = 0, _a = this.audios; _i < _a.length; _i++) {
|
|
355
|
+
var audio = _a[_i];
|
|
356
|
+
audio.muted = this.muted;
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
/**
|
|
360
|
+
* Unmute all audio
|
|
361
|
+
*/
|
|
362
|
+
Canvas.prototype.unmute = function () {
|
|
363
|
+
this.muted = false;
|
|
364
|
+
for (var _i = 0, _a = this.audios; _i < _a.length; _i++) {
|
|
365
|
+
var audio = _a[_i];
|
|
366
|
+
audio.muted = this.muted;
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
/**
|
|
370
|
+
* Determines whether audio is muted
|
|
371
|
+
* @returns True if currently muted
|
|
372
|
+
*/
|
|
373
|
+
Canvas.prototype.isMuted = function () {
|
|
374
|
+
return this.muted;
|
|
375
|
+
};
|
|
270
376
|
/**
|
|
271
377
|
* Draw an object onto the canvas.
|
|
272
378
|
* @param drawable Any drawable object
|
|
@@ -274,6 +380,9 @@ var Canvas = /** @class */ (function () {
|
|
|
274
380
|
*/
|
|
275
381
|
Canvas.prototype.draw = function (drawable, layer) {
|
|
276
382
|
if (layer === void 0) { layer = 0; }
|
|
383
|
+
if (layer < 0 || layer >= this.config.numLayers) {
|
|
384
|
+
throw new Error("Layer ".concat(layer, " is out of range. [0,").concat(this.config.numLayers, ")"));
|
|
385
|
+
}
|
|
277
386
|
drawable.draw(this.layers[layer]);
|
|
278
387
|
};
|
|
279
388
|
/**
|
|
@@ -282,6 +391,9 @@ var Canvas = /** @class */ (function () {
|
|
|
282
391
|
*/
|
|
283
392
|
Canvas.prototype.clear = function (layer) {
|
|
284
393
|
if (layer === void 0) { layer = -1; }
|
|
394
|
+
if (layer >= this.config.numLayers) {
|
|
395
|
+
throw new Error("Layer ".concat(layer, " is out of range. [0,").concat(this.config.numLayers, ")"));
|
|
396
|
+
}
|
|
285
397
|
if (layer < 0) {
|
|
286
398
|
for (var _i = 0, _a = this.layers; _i < _a.length; _i++) {
|
|
287
399
|
var layer_1 = _a[_i];
|
|
@@ -330,6 +442,7 @@ var Canvas = /** @class */ (function () {
|
|
|
330
442
|
borderBlur: 'transparent',
|
|
331
443
|
showMouse: true,
|
|
332
444
|
numLayers: 1,
|
|
445
|
+
numTracks: 1,
|
|
333
446
|
keydown: function () { return; },
|
|
334
447
|
keyup: function () { return; },
|
|
335
448
|
mousemove: function () { return; },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "graphico",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
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
|
@@ -42,6 +42,10 @@ export interface Options {
|
|
|
42
42
|
* The number of layers in this canvas
|
|
43
43
|
*/
|
|
44
44
|
readonly numLayers: number;
|
|
45
|
+
/**
|
|
46
|
+
* The number of audio tracks
|
|
47
|
+
*/
|
|
48
|
+
readonly numTracks: number;
|
|
45
49
|
/**
|
|
46
50
|
* Event listener for when a key is pressed
|
|
47
51
|
* @param key The key that was pressed
|