graphico 0.0.5 → 1.0.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,14 @@
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
+ - Simple, object-oriented canvas API for organized graphics programming
8
+ - Easy debugging and extensive configuration
9
+ - Supports multiple canvas layers with transparency
10
+ - Hardware-accelerated graphics and animation
11
+ - User interaction via keyboard or mouse inputs
12
+ - Built-in logic for screenshots and screen recordings
13
+
14
+ 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
  */
@@ -47,40 +47,45 @@ var Canvas = /** @class */ (function () {
47
47
  this.config = Canvas.setDefaults(options, Canvas.defaults);
48
48
  this.width = this.config.width;
49
49
  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);
50
+ // Create the main <canvas> element and set properties
51
+ var main = document.createElement('canvas');
52
+ main.tabIndex = 1; // For element focus
53
+ main.style.outline = 'none';
54
+ main.style.imageRendering = 'pixelated';
55
+ main.width = this.config.width;
56
+ main.height = this.config.height;
57
+ main.style.width = "".concat(this.config.width * this.config.scale, "px");
58
+ main.style.height = "".concat(this.config.height * this.config.scale, "px");
59
+ main.style.border = "".concat(this.config.scale, "px solid ").concat(this.config.border);
60
+ main.style.cursor = this.config.showMouse ? 'default' : 'none';
61
+ this.config.parent.appendChild(main);
62
+ // Create main canvas graphics object
63
+ var graphics = main.getContext('2d');
64
+ if (graphics) {
65
+ this.graphic = graphics;
66
+ }
67
+ else {
68
+ throw new Error('Could not initialize canvas graphics.');
69
+ }
70
+ graphics.imageSmoothingEnabled = false;
61
71
  // Create canvas layers
62
72
  for (var i = 0; i < this.config.numLayers; i++) {
63
73
  var canvas = document.createElement('canvas');
64
- var graphics = canvas.getContext('2d');
65
- if (graphics) {
66
- this.graphics.push(graphics);
74
+ var layer = canvas.getContext('2d');
75
+ if (layer) {
76
+ this.layers.push(layer);
67
77
  }
68
78
  else {
69
79
  throw new Error('Could not initialize canvas graphics.');
70
80
  }
71
81
  // Set properties for canvas
72
82
  canvas.style.imageRendering = 'pixelated';
73
- canvas.style.boxSizing = 'border-box';
74
83
  canvas.width = this.config.width;
75
84
  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);
85
+ layer.imageSmoothingEnabled = false;
81
86
  }
82
87
  // Event listeners
83
- container.addEventListener('mousemove', function (e) {
88
+ main.addEventListener('mousemove', function (e) {
84
89
  if (!_this.focused) {
85
90
  return;
86
91
  }
@@ -89,7 +94,7 @@ var Canvas = /** @class */ (function () {
89
94
  _this.log(e.type, _this.mouseX, _this.mouseY);
90
95
  _this.config.mousemove(_this.mouseX, _this.mouseY);
91
96
  });
92
- container.addEventListener('keydown', function (e) {
97
+ main.addEventListener('keydown', function (e) {
93
98
  if (!_this.focused) {
94
99
  return;
95
100
  }
@@ -101,7 +106,7 @@ var Canvas = /** @class */ (function () {
101
106
  _this.config.keydown(key);
102
107
  }
103
108
  });
104
- container.addEventListener('keyup', function (e) {
109
+ main.addEventListener('keyup', function (e) {
105
110
  if (!_this.focused) {
106
111
  return;
107
112
  }
@@ -113,7 +118,7 @@ var Canvas = /** @class */ (function () {
113
118
  _this.config.keyup(key);
114
119
  }
115
120
  });
116
- container.addEventListener('mousedown', function (e) {
121
+ main.addEventListener('mousedown', function (e) {
117
122
  if (!_this.focused) {
118
123
  return;
119
124
  }
@@ -124,7 +129,7 @@ var Canvas = /** @class */ (function () {
124
129
  _this.config.mousedown(button);
125
130
  }
126
131
  });
127
- container.addEventListener('mouseup', function (e) {
132
+ main.addEventListener('mouseup', function (e) {
128
133
  if (!_this.focused) {
129
134
  return;
130
135
  }
@@ -136,15 +141,15 @@ var Canvas = /** @class */ (function () {
136
141
  _this.config.mouseup(button);
137
142
  }
138
143
  });
139
- container.addEventListener('focusin', function (e) {
144
+ main.addEventListener('focusin', function (e) {
140
145
  _this.focused = true;
141
- container.style.borderColor = _this.config.border;
146
+ main.style.borderColor = _this.config.border;
142
147
  _this.log(e.type, _this.focused);
143
148
  _this.animation = requestAnimationFrame(function (time) { return _this.startAnimate(time); });
144
149
  });
145
- container.addEventListener('focusout', function (e) {
150
+ main.addEventListener('focusout', function (e) {
146
151
  _this.focused = false;
147
- container.style.borderColor = _this.config.borderBlur;
152
+ main.style.borderColor = _this.config.borderBlur;
148
153
  _this.log(e.type, _this.focused);
149
154
  cancelAnimationFrame(_this.animation);
150
155
  });
@@ -152,9 +157,30 @@ var Canvas = /** @class */ (function () {
152
157
  _this.log(e.type);
153
158
  cancelAnimationFrame(_this.animation);
154
159
  });
155
- container.addEventListener('contextmenu', function (e) { return e.preventDefault(); });
160
+ main.addEventListener('contextmenu', function (e) { return e.preventDefault(); });
156
161
  // Focus on the canvas
157
- container.focus();
162
+ main.focus();
163
+ // Initialize the media recorder
164
+ var recordPart = [];
165
+ this.recorder = new MediaRecorder(main.captureStream());
166
+ this.recorder.addEventListener('dataavailable', function (e) {
167
+ _this.log(e.type);
168
+ recordPart.push(e.data);
169
+ });
170
+ this.recorder.addEventListener('stop', function (e) {
171
+ _this.log(e.type);
172
+ var recording = new Blob(recordPart, { type: 'video/webm;codecs=h264' });
173
+ var url = URL.createObjectURL(recording);
174
+ var downloadLink = document.createElement('a');
175
+ downloadLink.setAttribute('href', url);
176
+ downloadLink.setAttribute('download', "recording-".concat(Date.now()));
177
+ downloadLink.click();
178
+ // Clear out the existing blob parts for recording a new capture
179
+ recordPart.splice(0);
180
+ // Remove all keys and mouse buttons down because we lose focus
181
+ _this.keys.splice(0);
182
+ _this.mouseButtons.splice(0);
183
+ });
158
184
  }
159
185
  /**
160
186
  * Start the animation.
@@ -173,8 +199,14 @@ var Canvas = /** @class */ (function () {
173
199
  var currentFrame = time;
174
200
  var dt = currentFrame - this.lastFrame;
175
201
  this.lastFrame = currentFrame;
176
- this.log('animate', dt, currentFrame);
177
202
  this.config.loop(dt);
203
+ // Draw all the layers onto the main canvas
204
+ this.graphic.fillStyle = this.config.background;
205
+ this.graphic.fillRect(0, 0, this.width, this.height);
206
+ for (var _i = 0, _a = this.layers; _i < _a.length; _i++) {
207
+ var layer = _a[_i];
208
+ this.graphic.drawImage(layer.canvas, 0, 0);
209
+ }
178
210
  this.animation = requestAnimationFrame(function (time) { return _this.animate(time); });
179
211
  };
180
212
  /**
@@ -206,22 +238,8 @@ var Canvas = /** @class */ (function () {
206
238
  */
207
239
  Canvas.prototype.screenshot = function (name) {
208
240
  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
241
  // Generate a data URL and set it as the download parameter for <a>
224
- var dataURL = screen.graphics[0].canvas.toDataURL();
242
+ var dataURL = this.graphic.canvas.toDataURL();
225
243
  var downloadLink = document.createElement('a');
226
244
  downloadLink.setAttribute('href', dataURL);
227
245
  downloadLink.setAttribute('download', name);
@@ -230,6 +248,25 @@ var Canvas = /** @class */ (function () {
230
248
  this.keys.splice(0);
231
249
  this.mouseButtons.splice(0);
232
250
  };
251
+ /**
252
+ * Start recording all layers on the canvas
253
+ */
254
+ Canvas.prototype.startRecording = function () {
255
+ this.recorder.start();
256
+ };
257
+ /**
258
+ * Stop recording and download screen capture
259
+ */
260
+ Canvas.prototype.stopRecording = function () {
261
+ this.recorder.stop();
262
+ };
263
+ /**
264
+ * Determines whether the media recorder is active
265
+ * @returns `true` if currently recording
266
+ */
267
+ Canvas.prototype.isRecording = function () {
268
+ return this.recorder.state === 'recording';
269
+ };
233
270
  /**
234
271
  * Draw an object onto the canvas.
235
272
  * @param drawable Any drawable object
@@ -237,7 +274,7 @@ var Canvas = /** @class */ (function () {
237
274
  */
238
275
  Canvas.prototype.draw = function (drawable, layer) {
239
276
  if (layer === void 0) { layer = 0; }
240
- drawable.draw(this.graphics[layer]);
277
+ drawable.draw(this.layers[layer]);
241
278
  };
242
279
  /**
243
280
  * Completely clears the canvas.
@@ -246,13 +283,13 @@ var Canvas = /** @class */ (function () {
246
283
  Canvas.prototype.clear = function (layer) {
247
284
  if (layer === void 0) { layer = -1; }
248
285
  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);
286
+ for (var _i = 0, _a = this.layers; _i < _a.length; _i++) {
287
+ var layer_1 = _a[_i];
288
+ layer_1.clearRect(0, 0, this.config.width, this.config.height);
252
289
  }
253
290
  }
254
291
  else {
255
- this.graphics[layer].clearRect(0, 0, this.config.width, this.config.height);
292
+ this.layers[layer].clearRect(0, 0, this.config.width, this.config.height);
256
293
  }
257
294
  };
258
295
  /**
@@ -288,7 +325,7 @@ var Canvas = /** @class */ (function () {
288
325
  width: 600,
289
326
  height: 400,
290
327
  scale: 1,
291
- background: 'transparent',
328
+ background: 'white',
292
329
  border: 'transparent',
293
330
  borderBlur: 'transparent',
294
331
  showMouse: true,
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.0.0",
4
4
  "description": "Canvas 2D rendering toolkit for games and visual projects",
5
5
  "homepage": "https://npm.nicfv.com/",
6
6
  "bin": "",
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,10 @@ export declare class Canvas {
50
55
  * Determine whether the client is focused or not
51
56
  */
52
57
  private focused;
58
+ /**
59
+ * The media recording object for screen captures
60
+ */
61
+ private readonly recorder;
53
62
  /**
54
63
  * Create a new canvas with the provided options
55
64
  * @param options Configuration options
@@ -85,6 +94,19 @@ export declare class Canvas {
85
94
  * @param name The file name of the screenshot
86
95
  */
87
96
  screenshot(name?: string): void;
97
+ /**
98
+ * Start recording all layers on the canvas
99
+ */
100
+ startRecording(): void;
101
+ /**
102
+ * Stop recording and download screen capture
103
+ */
104
+ stopRecording(): void;
105
+ /**
106
+ * Determines whether the media recorder is active
107
+ * @returns `true` if currently recording
108
+ */
109
+ isRecording(): boolean;
88
110
  /**
89
111
  * Draw an object onto the canvas.
90
112
  * @param drawable Any drawable object
@@ -105,90 +127,3 @@ export declare class Canvas {
105
127
  */
106
128
  private static setDefaults;
107
129
  }
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
134
- */
135
- readonly background: string;
136
- /**
137
- * The border color for the canvas (when focused)
138
- */
139
- readonly border: string;
140
- /**
141
- * The border color for the canvas (when not focused)
142
- */
143
- readonly borderBlur: string;
144
- /**
145
- * Optionally show or hide the mouse when hovering over the canvas
146
- */
147
- readonly showMouse: boolean;
148
- /**
149
- * The number of layers in this canvas
150
- */
151
- readonly numLayers: number;
152
- /**
153
- * Event listener for when a key is pressed
154
- * @param key The key that was pressed
155
- */
156
- readonly keydown: (key: string) => void;
157
- /**
158
- * Event listener for when a key is released
159
- * @param key The key that was released
160
- */
161
- readonly keyup: (key: string) => void;
162
- /**
163
- * Event listener for when the mouse is moved
164
- * @param x Cursor X-coordinate
165
- * @param y Cursor Y-coordinate
166
- */
167
- readonly mousemove: (x: number, y: number) => void;
168
- /**
169
- * Event listener for when a button on the mouse is pressed
170
- * @param button The button that was pressed
171
- */
172
- readonly mousedown: (button: number) => void;
173
- /**
174
- * Event listener for when a button on the mouse is released
175
- * @param button The button that was released
176
- */
177
- readonly mouseup: (button: number) => void;
178
- /**
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
182
- */
183
- readonly loop: (dt: number) => void;
184
- }
185
- /**
186
- * Represents an object that can be drawn on the canvas.
187
- */
188
- export interface Drawable {
189
- /**
190
- * Draw this object onto the canvas.
191
- * @param graphics Canvas 2D rendering interface
192
- */
193
- draw(graphics: CanvasRenderingContext2D): void;
194
- }
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,87 @@
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
+ * Event listener for when a key is pressed
47
+ * @param key The key that was pressed
48
+ */
49
+ readonly keydown: (key: string) => void;
50
+ /**
51
+ * Event listener for when a key is released
52
+ * @param key The key that was released
53
+ */
54
+ readonly keyup: (key: string) => void;
55
+ /**
56
+ * Event listener for when the mouse is moved
57
+ * @param x Cursor X-coordinate
58
+ * @param y Cursor Y-coordinate
59
+ */
60
+ readonly mousemove: (x: number, y: number) => void;
61
+ /**
62
+ * Event listener for when a button on the mouse is pressed
63
+ * @param button The button that was pressed
64
+ */
65
+ readonly mousedown: (button: number) => void;
66
+ /**
67
+ * Event listener for when a button on the mouse is released
68
+ * @param button The button that was released
69
+ */
70
+ readonly mouseup: (button: number) => void;
71
+ /**
72
+ * Event listener for a the main animation loop
73
+ * @param dt The number of milliseconds in between frames
74
+ * @returns An array of `Drawable` to render on layer 0, or void
75
+ */
76
+ readonly loop: (dt: number) => void;
77
+ }
78
+ /**
79
+ * Represents an object that can be drawn on the canvas.
80
+ */
81
+ export interface Drawable {
82
+ /**
83
+ * Draw this object onto the canvas.
84
+ * @param graphics Canvas 2D rendering interface
85
+ */
86
+ draw(graphics: CanvasRenderingContext2D): void;
87
+ }