graphico 0.0.3 → 0.0.5

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/canvas.js CHANGED
@@ -12,6 +12,10 @@ var Canvas = /** @class */ (function () {
12
12
  function Canvas(options) {
13
13
  if (options === void 0) { options = {}; }
14
14
  var _this = this;
15
+ /**
16
+ * Can be used to render 2D graphics onto the canvas
17
+ */
18
+ this.graphics = [];
15
19
  /**
16
20
  * Contains a list of current keys pressed
17
21
  */
@@ -36,34 +40,48 @@ var Canvas = /** @class */ (function () {
36
40
  * The last frame's high resolution timestamp
37
41
  */
38
42
  this.lastFrame = 0;
43
+ /**
44
+ * Determine whether the client is focused or not
45
+ */
46
+ this.focused = false;
39
47
  this.config = Canvas.setDefaults(options, Canvas.defaults);
40
48
  this.width = this.config.width;
41
49
  this.height = this.config.height;
42
- var canvas = document.createElement('canvas');
43
- var graphics = canvas.getContext('2d');
44
- if (graphics) {
45
- this.graphics = graphics;
46
- }
47
- else {
48
- throw new Error('Could not initialize canvas graphics.');
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);
61
+ // Create canvas layers
62
+ for (var i = 0; i < this.config.numLayers; i++) {
63
+ var canvas = document.createElement('canvas');
64
+ var graphics = canvas.getContext('2d');
65
+ if (graphics) {
66
+ this.graphics.push(graphics);
67
+ }
68
+ else {
69
+ throw new Error('Could not initialize canvas graphics.');
70
+ }
71
+ // Set properties for canvas
72
+ canvas.style.imageRendering = 'pixelated';
73
+ canvas.style.boxSizing = 'border-box';
74
+ canvas.width = this.config.width;
75
+ 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);
49
81
  }
50
- // Set static properties
51
- this.config.parent.appendChild(canvas);
52
- canvas.tabIndex = 1; // For element focus
53
- canvas.style.outline = 'none';
54
- canvas.style.imageRendering = 'pixelated';
55
- graphics.imageSmoothingEnabled = false;
56
- // Set custom properties
57
- canvas.width = this.config.width;
58
- canvas.height = this.config.height;
59
- canvas.style.width = "".concat(this.config.width * this.config.scale, "px");
60
- canvas.style.height = "".concat(this.config.height * this.config.scale, "px");
61
- canvas.style.background = this.config.background.toString();
62
- canvas.style.border = "".concat(this.config.scale, "px solid ").concat(this.config.border);
63
- canvas.style.cursor = this.config.showMouse ? 'default' : 'none';
64
82
  // Event listeners
65
- canvas.addEventListener('mousemove', function (e) {
66
- if (!_this.isFocused()) {
83
+ container.addEventListener('mousemove', function (e) {
84
+ if (!_this.focused) {
67
85
  return;
68
86
  }
69
87
  _this.mouseX = (e.offsetX / _this.config.scale) | 0;
@@ -71,8 +89,8 @@ var Canvas = /** @class */ (function () {
71
89
  _this.log(e.type, _this.mouseX, _this.mouseY);
72
90
  _this.config.mousemove(_this.mouseX, _this.mouseY);
73
91
  });
74
- canvas.addEventListener('keydown', function (e) {
75
- if (!_this.isFocused()) {
92
+ container.addEventListener('keydown', function (e) {
93
+ if (!_this.focused) {
76
94
  return;
77
95
  }
78
96
  e.preventDefault();
@@ -83,8 +101,8 @@ var Canvas = /** @class */ (function () {
83
101
  _this.config.keydown(key);
84
102
  }
85
103
  });
86
- canvas.addEventListener('keyup', function (e) {
87
- if (!_this.isFocused()) {
104
+ container.addEventListener('keyup', function (e) {
105
+ if (!_this.focused) {
88
106
  return;
89
107
  }
90
108
  var key = e.key.toLowerCase();
@@ -95,8 +113,8 @@ var Canvas = /** @class */ (function () {
95
113
  _this.config.keyup(key);
96
114
  }
97
115
  });
98
- canvas.addEventListener('mousedown', function (e) {
99
- if (!_this.isFocused()) {
116
+ container.addEventListener('mousedown', function (e) {
117
+ if (!_this.focused) {
100
118
  return;
101
119
  }
102
120
  var button = e.button;
@@ -106,8 +124,8 @@ var Canvas = /** @class */ (function () {
106
124
  _this.config.mousedown(button);
107
125
  }
108
126
  });
109
- canvas.addEventListener('mouseup', function (e) {
110
- if (!_this.isFocused()) {
127
+ container.addEventListener('mouseup', function (e) {
128
+ if (!_this.focused) {
111
129
  return;
112
130
  }
113
131
  var button = e.button;
@@ -118,30 +136,26 @@ var Canvas = /** @class */ (function () {
118
136
  _this.config.mouseup(button);
119
137
  }
120
138
  });
121
- canvas.addEventListener('focusin', function (e) {
122
- canvas.style.borderColor = _this.config.border;
123
- _this.log(e.type);
139
+ container.addEventListener('focusin', function (e) {
140
+ _this.focused = true;
141
+ container.style.borderColor = _this.config.border;
142
+ _this.log(e.type, _this.focused);
124
143
  _this.animation = requestAnimationFrame(function (time) { return _this.startAnimate(time); });
125
144
  });
126
- canvas.addEventListener('focusout', function (e) {
127
- canvas.style.borderColor = _this.config.borderBlur;
128
- _this.log(e.type);
145
+ container.addEventListener('focusout', function (e) {
146
+ _this.focused = false;
147
+ container.style.borderColor = _this.config.borderBlur;
148
+ _this.log(e.type, _this.focused);
129
149
  cancelAnimationFrame(_this.animation);
130
150
  });
131
151
  window.addEventListener('blur', function (e) {
132
152
  _this.log(e.type);
133
153
  cancelAnimationFrame(_this.animation);
134
154
  });
135
- canvas.addEventListener('contextmenu', function (e) { return e.preventDefault(); });
155
+ container.addEventListener('contextmenu', function (e) { return e.preventDefault(); });
136
156
  // Focus on the canvas
137
- canvas.focus();
157
+ container.focus();
138
158
  }
139
- /**
140
- * Determine if the canvas is currently focused.
141
- */
142
- Canvas.prototype.isFocused = function () {
143
- return this.graphics.canvas === document.activeElement;
144
- };
145
159
  /**
146
160
  * Start the animation.
147
161
  */
@@ -156,16 +170,11 @@ var Canvas = /** @class */ (function () {
156
170
  */
157
171
  Canvas.prototype.animate = function (time) {
158
172
  var _this = this;
159
- var _a;
160
173
  var currentFrame = time;
161
174
  var dt = currentFrame - this.lastFrame;
162
175
  this.lastFrame = currentFrame;
163
176
  this.log('animate', dt, currentFrame);
164
- var drawables = (_a = this.config.loop(dt)) !== null && _a !== void 0 ? _a : [];
165
- for (var _i = 0, drawables_1 = drawables; _i < drawables_1.length; _i++) {
166
- var drawable = drawables_1[_i];
167
- this.draw(drawable);
168
- }
177
+ this.config.loop(dt);
169
178
  this.animation = requestAnimationFrame(function (time) { return _this.animate(time); });
170
179
  };
171
180
  /**
@@ -191,55 +200,60 @@ var Canvas = /** @class */ (function () {
191
200
  Canvas.prototype.getMousePosition = function () {
192
201
  return [this.mouseX, this.mouseY];
193
202
  };
194
- /**
195
- * Get the color of the selected pixel.
196
- * @param x The pixel's x-coordinate
197
- * @param y The pixel's y-coordinate
198
- * @returns `[red, green, blue, alpha]`
199
- */
200
- Canvas.prototype.getPixel = function (x, y) {
201
- var data = this.graphics.getImageData(x, y, 1, 1).data;
202
- console.log(this.graphics.getImageData(x, y, 2, 2));
203
- ;
204
- return [data[0], data[1], data[2], data[3]];
205
- };
206
- /**
207
- * Set the color of the selected pixel.
208
- * @param x The pixel's x-coordinate
209
- * @param y The pixel's y-coordinate
210
- * @param color `[red, green, blue, alpha]`
211
- */
212
- Canvas.prototype.setPixel = function (x, y, color) {
213
- var data = this.graphics.getImageData(x, y, 1, 1);
214
- data.data[0] = color[0];
215
- data.data[1] = color[1];
216
- data.data[2] = color[2];
217
- data.data[3] = color[3];
218
- console.log(data);
219
- this.graphics.putImageData(data, x, y);
220
- };
221
203
  /**
222
204
  * Take a screenshot of the canvas contents and save to a .png file.
205
+ * @param name The file name of the screenshot
223
206
  */
224
- Canvas.prototype.screenshot = function () {
225
- var dataURL = this.graphics.canvas.toDataURL();
207
+ Canvas.prototype.screenshot = function (name) {
208
+ 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
+ // Generate a data URL and set it as the download parameter for <a>
224
+ var dataURL = screen.graphics[0].canvas.toDataURL();
226
225
  var downloadLink = document.createElement('a');
227
226
  downloadLink.setAttribute('href', dataURL);
228
- downloadLink.setAttribute('download', 'screenshot');
227
+ downloadLink.setAttribute('download', name);
229
228
  downloadLink.click();
229
+ // Remove all keys and mouse buttons down because we lose focus
230
+ this.keys.splice(0);
231
+ this.mouseButtons.splice(0);
230
232
  };
231
233
  /**
232
234
  * Draw an object onto the canvas.
233
235
  * @param drawable Any drawable object
236
+ * @param layer The zero-indexed layer to draw to
234
237
  */
235
- Canvas.prototype.draw = function (drawable) {
236
- drawable.draw(this.graphics);
238
+ Canvas.prototype.draw = function (drawable, layer) {
239
+ if (layer === void 0) { layer = 0; }
240
+ drawable.draw(this.graphics[layer]);
237
241
  };
238
242
  /**
239
243
  * Completely clears the canvas.
244
+ * @param layer The zero-indexed layer to clear, if unset, will clear all layers
240
245
  */
241
- Canvas.prototype.clear = function () {
242
- this.graphics.clearRect(0, 0, this.config.width, this.config.height);
246
+ Canvas.prototype.clear = function (layer) {
247
+ if (layer === void 0) { layer = -1; }
248
+ 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);
252
+ }
253
+ }
254
+ else {
255
+ this.graphics[layer].clearRect(0, 0, this.config.width, this.config.height);
256
+ }
243
257
  };
244
258
  /**
245
259
  * Log a message to the debug console.
@@ -278,6 +292,7 @@ var Canvas = /** @class */ (function () {
278
292
  border: 'transparent',
279
293
  borderBlur: 'transparent',
280
294
  showMouse: true,
295
+ numLayers: 1,
281
296
  keydown: function () { return; },
282
297
  keyup: function () { return; },
283
298
  mousemove: function () { return; },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "graphico",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
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
@@ -46,15 +46,15 @@ export declare class Canvas {
46
46
  * The last frame's high resolution timestamp
47
47
  */
48
48
  private lastFrame;
49
+ /**
50
+ * Determine whether the client is focused or not
51
+ */
52
+ private focused;
49
53
  /**
50
54
  * Create a new canvas with the provided options
51
55
  * @param options Configuration options
52
56
  */
53
57
  constructor(options?: Partial<Options>);
54
- /**
55
- * Determine if the canvas is currently focused.
56
- */
57
- private isFocused;
58
58
  /**
59
59
  * Start the animation.
60
60
  */
@@ -80,33 +80,22 @@ export declare class Canvas {
80
80
  * @returns Cursor position as `[x, y]`
81
81
  */
82
82
  getMousePosition(): [number, number];
83
- /**
84
- * Get the color of the selected pixel.
85
- * @param x The pixel's x-coordinate
86
- * @param y The pixel's y-coordinate
87
- * @returns `[red, green, blue, alpha]`
88
- */
89
- getPixel(x: number, y: number): [number, number, number, number];
90
- /**
91
- * Set the color of the selected pixel.
92
- * @param x The pixel's x-coordinate
93
- * @param y The pixel's y-coordinate
94
- * @param color `[red, green, blue, alpha]`
95
- */
96
- setPixel(x: number, y: number, color: [number, number, number, number]): void;
97
83
  /**
98
84
  * Take a screenshot of the canvas contents and save to a .png file.
85
+ * @param name The file name of the screenshot
99
86
  */
100
- screenshot(): void;
87
+ screenshot(name?: string): void;
101
88
  /**
102
89
  * Draw an object onto the canvas.
103
90
  * @param drawable Any drawable object
91
+ * @param layer The zero-indexed layer to draw to
104
92
  */
105
- draw(drawable: Drawable): void;
93
+ draw(drawable: Drawable, layer?: number): void;
106
94
  /**
107
95
  * Completely clears the canvas.
96
+ * @param layer The zero-indexed layer to clear, if unset, will clear all layers
108
97
  */
109
- clear(): void;
98
+ clear(layer?: number): void;
110
99
  /**
111
100
  * Log a message to the debug console.
112
101
  */
@@ -156,6 +145,10 @@ export interface Options {
156
145
  * Optionally show or hide the mouse when hovering over the canvas
157
146
  */
158
147
  readonly showMouse: boolean;
148
+ /**
149
+ * The number of layers in this canvas
150
+ */
151
+ readonly numLayers: number;
159
152
  /**
160
153
  * Event listener for when a key is pressed
161
154
  * @param key The key that was pressed
@@ -185,9 +178,9 @@ export interface Options {
185
178
  /**
186
179
  * Event listener for a the main animation loop
187
180
  * @param dt The number of milliseconds in between frames
188
- * @returns An array of `Drawable` to render, or void
181
+ * @returns An array of `Drawable` to render on layer 0, or void
189
182
  */
190
- readonly loop: (dt: number) => Drawable[] | (void | never);
183
+ readonly loop: (dt: number) => void;
191
184
  }
192
185
  /**
193
186
  * Represents an object that can be drawn on the canvas.