graphico 0.0.5 → 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 CHANGED
@@ -1,3 +1,23 @@
1
1
  ## Getting Started
2
2
 
3
- !!! THIS PACKAGE IS STILL UNDER DEVELOPMENT AND WILL BE UNSTABLE !!!
3
+ `graphico` is a package used for creating games, animations, and other visual projects. It simplifies canvas 2D rendering within the browser and provides the foundation for user interaction.
4
+
5
+ ## Features
6
+
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
@@ -13,9 +13,9 @@ var Canvas = /** @class */ (function () {
13
13
  if (options === void 0) { options = {}; }
14
14
  var _this = this;
15
15
  /**
16
- * Can be used to render 2D graphics onto the canvas
16
+ * Can be used to render 2D graphics onto layers of the canvas
17
17
  */
18
- this.graphics = [];
18
+ this.layers = [];
19
19
  /**
20
20
  * Contains a list of current keys pressed
21
21
  */
@@ -44,43 +44,60 @@ 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;
50
- // Create the container <div> element and set properties
51
- var container = document.createElement('div');
52
- container.tabIndex = 1; // For element focus
53
- container.style.outline = 'none';
54
- container.style.width = "".concat(this.config.width * this.config.scale, "px");
55
- container.style.height = "".concat(this.config.height * this.config.scale, "px");
56
- container.style.border = "".concat(this.config.scale, "px solid ").concat(this.config.border);
57
- container.style.background = this.config.background;
58
- container.style.cursor = this.config.showMouse ? 'default' : 'none';
59
- container.style.position = 'relative';
60
- this.config.parent.appendChild(container);
62
+ // Create the main <canvas> element and set properties
63
+ var main = document.createElement('canvas');
64
+ main.tabIndex = 1; // For element focus
65
+ main.style.outline = 'none';
66
+ main.style.imageRendering = 'pixelated';
67
+ main.width = this.config.width;
68
+ main.height = this.config.height;
69
+ main.style.width = "".concat(this.config.width * this.config.scale, "px");
70
+ main.style.height = "".concat(this.config.height * this.config.scale, "px");
71
+ main.style.border = "".concat(this.config.scale, "px solid ").concat(this.config.border);
72
+ main.style.cursor = this.config.showMouse ? 'default' : 'none';
73
+ this.config.parent.appendChild(main);
74
+ // Create main canvas graphics object
75
+ var graphics = main.getContext('2d');
76
+ if (graphics) {
77
+ this.graphic = graphics;
78
+ }
79
+ else {
80
+ throw new Error('Could not initialize canvas graphics.');
81
+ }
82
+ graphics.imageSmoothingEnabled = false;
61
83
  // Create canvas layers
62
84
  for (var i = 0; i < this.config.numLayers; i++) {
63
85
  var canvas = document.createElement('canvas');
64
- var graphics = canvas.getContext('2d');
65
- if (graphics) {
66
- this.graphics.push(graphics);
86
+ var layer = canvas.getContext('2d');
87
+ if (layer) {
88
+ this.layers.push(layer);
67
89
  }
68
90
  else {
69
91
  throw new Error('Could not initialize canvas graphics.');
70
92
  }
71
93
  // Set properties for canvas
72
94
  canvas.style.imageRendering = 'pixelated';
73
- canvas.style.boxSizing = 'border-box';
74
95
  canvas.width = this.config.width;
75
96
  canvas.height = this.config.height;
76
- canvas.style.width = '100%';
77
- canvas.style.height = '100%';
78
- canvas.style.position = 'absolute';
79
- graphics.imageSmoothingEnabled = false;
80
- container.appendChild(canvas);
97
+ layer.imageSmoothingEnabled = false;
81
98
  }
82
99
  // Event listeners
83
- container.addEventListener('mousemove', function (e) {
100
+ main.addEventListener('mousemove', function (e) {
84
101
  if (!_this.focused) {
85
102
  return;
86
103
  }
@@ -89,7 +106,9 @@ var Canvas = /** @class */ (function () {
89
106
  _this.log(e.type, _this.mouseX, _this.mouseY);
90
107
  _this.config.mousemove(_this.mouseX, _this.mouseY);
91
108
  });
92
- container.addEventListener('keydown', function (e) {
109
+ main.addEventListener('keydown', function (e) {
110
+ audioContext.resume();
111
+ _this.interacted = true;
93
112
  if (!_this.focused) {
94
113
  return;
95
114
  }
@@ -101,7 +120,7 @@ var Canvas = /** @class */ (function () {
101
120
  _this.config.keydown(key);
102
121
  }
103
122
  });
104
- container.addEventListener('keyup', function (e) {
123
+ main.addEventListener('keyup', function (e) {
105
124
  if (!_this.focused) {
106
125
  return;
107
126
  }
@@ -113,7 +132,9 @@ var Canvas = /** @class */ (function () {
113
132
  _this.config.keyup(key);
114
133
  }
115
134
  });
116
- container.addEventListener('mousedown', function (e) {
135
+ main.addEventListener('mousedown', function (e) {
136
+ audioContext.resume();
137
+ _this.interacted = true;
117
138
  if (!_this.focused) {
118
139
  return;
119
140
  }
@@ -124,7 +145,7 @@ var Canvas = /** @class */ (function () {
124
145
  _this.config.mousedown(button);
125
146
  }
126
147
  });
127
- container.addEventListener('mouseup', function (e) {
148
+ main.addEventListener('mouseup', function (e) {
128
149
  if (!_this.focused) {
129
150
  return;
130
151
  }
@@ -136,15 +157,15 @@ var Canvas = /** @class */ (function () {
136
157
  _this.config.mouseup(button);
137
158
  }
138
159
  });
139
- container.addEventListener('focusin', function (e) {
160
+ main.addEventListener('focusin', function (e) {
140
161
  _this.focused = true;
141
- container.style.borderColor = _this.config.border;
162
+ main.style.borderColor = _this.config.border;
142
163
  _this.log(e.type, _this.focused);
143
164
  _this.animation = requestAnimationFrame(function (time) { return _this.startAnimate(time); });
144
165
  });
145
- container.addEventListener('focusout', function (e) {
166
+ main.addEventListener('focusout', function (e) {
146
167
  _this.focused = false;
147
- container.style.borderColor = _this.config.borderBlur;
168
+ main.style.borderColor = _this.config.borderBlur;
148
169
  _this.log(e.type, _this.focused);
149
170
  cancelAnimationFrame(_this.animation);
150
171
  });
@@ -152,9 +173,46 @@ var Canvas = /** @class */ (function () {
152
173
  _this.log(e.type);
153
174
  cancelAnimationFrame(_this.animation);
154
175
  });
155
- container.addEventListener('contextmenu', function (e) { return e.preventDefault(); });
176
+ main.addEventListener('contextmenu', function (e) { return e.preventDefault(); });
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
+ }
193
+ // Initialize the media recorder
194
+ var recordPart = [];
195
+ this.recorder = new MediaRecorder(stream);
196
+ this.recorder.addEventListener('dataavailable', function (e) {
197
+ _this.log(e.type);
198
+ recordPart.push(e.data);
199
+ });
200
+ this.recorder.addEventListener('stop', function (e) {
201
+ _this.log(e.type);
202
+ var recording = new Blob(recordPart, { type: 'video/webm;codecs=h264' });
203
+ var url = URL.createObjectURL(recording);
204
+ var downloadLink = document.createElement('a');
205
+ downloadLink.setAttribute('href', url);
206
+ downloadLink.setAttribute('download', "recording-".concat(Date.now()));
207
+ downloadLink.click();
208
+ // Clear out the existing blob parts for recording a new capture
209
+ recordPart.splice(0);
210
+ // Remove all keys and mouse buttons down because we lose focus
211
+ _this.keys.splice(0);
212
+ _this.mouseButtons.splice(0);
213
+ });
156
214
  // Focus on the canvas
157
- container.focus();
215
+ main.focus();
158
216
  }
159
217
  /**
160
218
  * Start the animation.
@@ -173,8 +231,14 @@ var Canvas = /** @class */ (function () {
173
231
  var currentFrame = time;
174
232
  var dt = currentFrame - this.lastFrame;
175
233
  this.lastFrame = currentFrame;
176
- this.log('animate', dt, currentFrame);
177
234
  this.config.loop(dt);
235
+ // Draw all the layers onto the main canvas
236
+ this.graphic.fillStyle = this.config.background;
237
+ this.graphic.fillRect(0, 0, this.width, this.height);
238
+ for (var _i = 0, _a = this.layers; _i < _a.length; _i++) {
239
+ var layer = _a[_i];
240
+ this.graphic.drawImage(layer.canvas, 0, 0);
241
+ }
178
242
  this.animation = requestAnimationFrame(function (time) { return _this.animate(time); });
179
243
  };
180
244
  /**
@@ -206,22 +270,8 @@ var Canvas = /** @class */ (function () {
206
270
  */
207
271
  Canvas.prototype.screenshot = function (name) {
208
272
  if (name === void 0) { name = 'screenshot'; }
209
- // Create an offscreen canvas
210
- var screen = new Canvas({
211
- parent: document.createElement('div'),
212
- height: this.config.height,
213
- width: this.config.width,
214
- scale: this.config.scale,
215
- });
216
- // Draw the background and each layer
217
- screen.graphics[0].fillStyle = this.config.background;
218
- screen.graphics[0].fillRect(0, 0, screen.width, screen.height);
219
- for (var _i = 0, _a = this.graphics; _i < _a.length; _i++) {
220
- var graphic = _a[_i];
221
- screen.graphics[0].drawImage(graphic.canvas, 0, 0);
222
- }
223
273
  // Generate a data URL and set it as the download parameter for <a>
224
- var dataURL = screen.graphics[0].canvas.toDataURL();
274
+ var dataURL = this.graphic.canvas.toDataURL();
225
275
  var downloadLink = document.createElement('a');
226
276
  downloadLink.setAttribute('href', dataURL);
227
277
  downloadLink.setAttribute('download', name);
@@ -230,6 +280,99 @@ var Canvas = /** @class */ (function () {
230
280
  this.keys.splice(0);
231
281
  this.mouseButtons.splice(0);
232
282
  };
283
+ /**
284
+ * Start recording all layers on the canvas
285
+ */
286
+ Canvas.prototype.startRecording = function () {
287
+ if (!this.interacted) {
288
+ throw new Error('The user has not yet interacted with this canvas.');
289
+ }
290
+ this.recorder.start();
291
+ };
292
+ /**
293
+ * Stop recording and download screen capture
294
+ */
295
+ Canvas.prototype.stopRecording = function () {
296
+ this.recorder.stop();
297
+ };
298
+ /**
299
+ * Determines whether the media recorder is active
300
+ * @returns True if currently recording
301
+ */
302
+ Canvas.prototype.isRecording = function () {
303
+ return this.recorder.state === 'recording';
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
+ };
233
376
  /**
234
377
  * Draw an object onto the canvas.
235
378
  * @param drawable Any drawable object
@@ -237,7 +380,10 @@ var Canvas = /** @class */ (function () {
237
380
  */
238
381
  Canvas.prototype.draw = function (drawable, layer) {
239
382
  if (layer === void 0) { layer = 0; }
240
- drawable.draw(this.graphics[layer]);
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
+ }
386
+ drawable.draw(this.layers[layer]);
241
387
  };
242
388
  /**
243
389
  * Completely clears the canvas.
@@ -245,14 +391,17 @@ var Canvas = /** @class */ (function () {
245
391
  */
246
392
  Canvas.prototype.clear = function (layer) {
247
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
+ }
248
397
  if (layer < 0) {
249
- for (var _i = 0, _a = this.graphics; _i < _a.length; _i++) {
250
- var graphic = _a[_i];
251
- graphic.clearRect(0, 0, this.config.width, this.config.height);
398
+ for (var _i = 0, _a = this.layers; _i < _a.length; _i++) {
399
+ var layer_1 = _a[_i];
400
+ layer_1.clearRect(0, 0, this.config.width, this.config.height);
252
401
  }
253
402
  }
254
403
  else {
255
- this.graphics[layer].clearRect(0, 0, this.config.width, this.config.height);
404
+ this.layers[layer].clearRect(0, 0, this.config.width, this.config.height);
256
405
  }
257
406
  };
258
407
  /**
@@ -288,11 +437,12 @@ var Canvas = /** @class */ (function () {
288
437
  width: 600,
289
438
  height: 400,
290
439
  scale: 1,
291
- background: 'transparent',
440
+ background: 'white',
292
441
  border: 'transparent',
293
442
  borderBlur: 'transparent',
294
443
  showMouse: true,
295
444
  numLayers: 1,
445
+ numTracks: 1,
296
446
  keydown: function () { return; },
297
447
  keyup: function () { return; },
298
448
  mousemove: function () { return; },
package/dist/index.js CHANGED
@@ -22,3 +22,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
22
22
  * ![NPM Last Update](https://img.shields.io/npm/last-update/graphico)
23
23
  */
24
24
  __exportStar(require("./canvas"), exports);
25
+ __exportStar(require("./types"), exports);
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "graphico",
3
- "version": "0.0.5",
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
@@ -1,3 +1,4 @@
1
+ import { Drawable, Options } from '.';
1
2
  /**
2
3
  * Represents a canvas for drawing and animating
3
4
  */
@@ -11,9 +12,13 @@ export declare class Canvas {
11
12
  */
12
13
  private readonly config;
13
14
  /**
14
- * Can be used to render 2D graphics onto the canvas
15
+ * Used to render 2D objects onto the main canvas
15
16
  */
16
- private readonly graphics;
17
+ private readonly graphic;
18
+ /**
19
+ * Can be used to render 2D graphics onto layers of the canvas
20
+ */
21
+ private readonly layers;
17
22
  /**
18
23
  * Contains a list of current keys pressed
19
24
  */
@@ -50,6 +55,22 @@ export declare class Canvas {
50
55
  * Determine whether the client is focused or not
51
56
  */
52
57
  private focused;
58
+ /**
59
+ * Determine whether the user has interacted with this canvas
60
+ */
61
+ private interacted;
62
+ /**
63
+ * The media recording object for screen captures
64
+ */
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;
53
74
  /**
54
75
  * Create a new canvas with the provided options
55
76
  * @param options Configuration options
@@ -86,109 +107,60 @@ export declare class Canvas {
86
107
  */
87
108
  screenshot(name?: string): void;
88
109
  /**
89
- * Draw an object onto the canvas.
90
- * @param drawable Any drawable object
91
- * @param layer The zero-indexed layer to draw to
92
- */
93
- draw(drawable: Drawable, layer?: number): void;
94
- /**
95
- * Completely clears the canvas.
96
- * @param layer The zero-indexed layer to clear, if unset, will clear all layers
97
- */
98
- clear(layer?: number): void;
99
- /**
100
- * Log a message to the debug console.
101
- */
102
- private log;
103
- /**
104
- * Set defaults for all undefined options.
105
- */
106
- private static setDefaults;
107
- }
108
- /**
109
- * Configuration Options for Canvas
110
- */
111
- export interface Options {
112
- /**
113
- * Optionally print debug messages to the console
114
- */
115
- readonly debug: boolean;
116
- /**
117
- * Appends the canvas onto the parent element
118
- */
119
- readonly parent: Node;
120
- /**
121
- * The width of the drawing area, in pixels
122
- */
123
- readonly width: number;
124
- /**
125
- * The height of the drawing area, in pixels
126
- */
127
- readonly height: number;
128
- /**
129
- * The scale of the drawing area to the actual size of the canvas element
130
- */
131
- readonly scale: number;
132
- /**
133
- * The background color of the canvas
110
+ * Start recording all layers on the canvas
134
111
  */
135
- readonly background: string;
112
+ startRecording(): void;
136
113
  /**
137
- * The border color for the canvas (when focused)
114
+ * Stop recording and download screen capture
138
115
  */
139
- readonly border: string;
116
+ stopRecording(): void;
140
117
  /**
141
- * The border color for the canvas (when not focused)
118
+ * Determines whether the media recorder is active
119
+ * @returns True if currently recording
142
120
  */
143
- readonly borderBlur: string;
121
+ isRecording(): boolean;
144
122
  /**
145
- * Optionally show or hide the mouse when hovering over the canvas
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
146
128
  */
147
- readonly showMouse: boolean;
129
+ playAudio(src: string, loop?: boolean, volume?: number, track?: number): void;
148
130
  /**
149
- * The number of layers in this canvas
131
+ * Stop all audio tracks from playing
150
132
  */
151
- readonly numLayers: number;
133
+ stopAudio(track?: number): void;
152
134
  /**
153
- * Event listener for when a key is pressed
154
- * @param key The key that was pressed
135
+ * Mute all audio
155
136
  */
156
- readonly keydown: (key: string) => void;
137
+ mute(): void;
157
138
  /**
158
- * Event listener for when a key is released
159
- * @param key The key that was released
139
+ * Unmute all audio
160
140
  */
161
- readonly keyup: (key: string) => void;
141
+ unmute(): void;
162
142
  /**
163
- * Event listener for when the mouse is moved
164
- * @param x Cursor X-coordinate
165
- * @param y Cursor Y-coordinate
143
+ * Determines whether audio is muted
144
+ * @returns True if currently muted
166
145
  */
167
- readonly mousemove: (x: number, y: number) => void;
146
+ isMuted(): boolean;
168
147
  /**
169
- * Event listener for when a button on the mouse is pressed
170
- * @param button The button that was pressed
148
+ * Draw an object onto the canvas.
149
+ * @param drawable Any drawable object
150
+ * @param layer The zero-indexed layer to draw to
171
151
  */
172
- readonly mousedown: (button: number) => void;
152
+ draw(drawable: Drawable, layer?: number): void;
173
153
  /**
174
- * Event listener for when a button on the mouse is released
175
- * @param button The button that was released
154
+ * Completely clears the canvas.
155
+ * @param layer The zero-indexed layer to clear, if unset, will clear all layers
176
156
  */
177
- readonly mouseup: (button: number) => void;
157
+ clear(layer?: number): void;
178
158
  /**
179
- * Event listener for a the main animation loop
180
- * @param dt The number of milliseconds in between frames
181
- * @returns An array of `Drawable` to render on layer 0, or void
159
+ * Log a message to the debug console.
182
160
  */
183
- readonly loop: (dt: number) => void;
184
- }
185
- /**
186
- * Represents an object that can be drawn on the canvas.
187
- */
188
- export interface Drawable {
161
+ private log;
189
162
  /**
190
- * Draw this object onto the canvas.
191
- * @param graphics Canvas 2D rendering interface
163
+ * Set defaults for all undefined options.
192
164
  */
193
- draw(graphics: CanvasRenderingContext2D): void;
165
+ private static setDefaults;
194
166
  }
package/types/index.d.ts CHANGED
@@ -6,3 +6,4 @@
6
6
  * ![NPM Last Update](https://img.shields.io/npm/last-update/graphico)
7
7
  */
8
8
  export * from './canvas';
9
+ export * from './types';
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Configuration Options for Canvas
3
+ */
4
+ export interface Options {
5
+ /**
6
+ * Optionally print debug messages to the console
7
+ */
8
+ readonly debug: boolean;
9
+ /**
10
+ * Appends the canvas onto the parent element
11
+ */
12
+ readonly parent: Node;
13
+ /**
14
+ * The width of the drawing area, in pixels
15
+ */
16
+ readonly width: number;
17
+ /**
18
+ * The height of the drawing area, in pixels
19
+ */
20
+ readonly height: number;
21
+ /**
22
+ * The scale of the drawing area to the actual size of the canvas element
23
+ */
24
+ readonly scale: number;
25
+ /**
26
+ * The background color of the canvas
27
+ */
28
+ readonly background: string;
29
+ /**
30
+ * The border color for the canvas (when focused)
31
+ */
32
+ readonly border: string;
33
+ /**
34
+ * The border color for the canvas (when not focused)
35
+ */
36
+ readonly borderBlur: string;
37
+ /**
38
+ * Optionally show or hide the mouse when hovering over the canvas
39
+ */
40
+ readonly showMouse: boolean;
41
+ /**
42
+ * The number of layers in this canvas
43
+ */
44
+ readonly numLayers: number;
45
+ /**
46
+ * The number of audio tracks
47
+ */
48
+ readonly numTracks: number;
49
+ /**
50
+ * Event listener for when a key is pressed
51
+ * @param key The key that was pressed
52
+ */
53
+ readonly keydown: (key: string) => void;
54
+ /**
55
+ * Event listener for when a key is released
56
+ * @param key The key that was released
57
+ */
58
+ readonly keyup: (key: string) => void;
59
+ /**
60
+ * Event listener for when the mouse is moved
61
+ * @param x Cursor X-coordinate
62
+ * @param y Cursor Y-coordinate
63
+ */
64
+ readonly mousemove: (x: number, y: number) => void;
65
+ /**
66
+ * Event listener for when a button on the mouse is pressed
67
+ * @param button The button that was pressed
68
+ */
69
+ readonly mousedown: (button: number) => void;
70
+ /**
71
+ * Event listener for when a button on the mouse is released
72
+ * @param button The button that was released
73
+ */
74
+ readonly mouseup: (button: number) => void;
75
+ /**
76
+ * Event listener for a the main animation loop
77
+ * @param dt The number of milliseconds in between frames
78
+ * @returns An array of `Drawable` to render on layer 0, or void
79
+ */
80
+ readonly loop: (dt: number) => void;
81
+ }
82
+ /**
83
+ * Represents an object that can be drawn on the canvas.
84
+ */
85
+ export interface Drawable {
86
+ /**
87
+ * Draw this object onto the canvas.
88
+ * @param graphics Canvas 2D rendering interface
89
+ */
90
+ draw(graphics: CanvasRenderingContext2D): void;
91
+ }