It's fine to use the same canvas context for multiple purposes (in fact, preferred than destroying and re-creating the canvas just to clear and redraw it), but this seems somewhat antithetical to a class as shown here.
Classes are supposed to encapsulate data, but the setup here creates a false sense of encapsulation due to the HTMLCanvas parameter. In truth, if you make multiple instances of this class, they all share the same context, leading to a potentially confusing situation for the client of the class when multiple Canvas instances corrupt each other's state.
The benefit of hiding the parameters to the canvas clearRect function seems negligible. Sure, you may add more features to better motivate it, but there's still a potential data sharing problem as well as an unclear benefit/payoff for the whole enterprise even with the sharing fixed.
Here's a demonstration of what I mean:
class Canvas {
constructor(HTMLCanvas) {
this.context = HTMLCanvas.getContext("2d");
this.width = HTMLCanvas.width;
this.height = HTMLCanvas.height;
}
clear() {
this.context.clearRect(0, 0, this.width, this.height);
}
}
const canvas = document.createElement("canvas");
document.body.append(canvas);
const canvas1 = new Canvas(canvas);
const canvas2 = new Canvas(canvas);
canvas1.context.fillRect(0, 0, 30, 30);
canvas2.context.fillRect(30, 30, 30, 30);
It's hard to see the benefit here. As a client of your class, I've allocated 2 whole objects but they basically are views into the same canvas, leading to drawing on one to affect the other canvas. Calling clear would wipe both canvases and there's really no per-instance unique data to speak of. I'd have to explicitly provide two separate canvases to get normal usage and I've already dug myself into a hole of added verbosity and potential confusion before seeing any good come of it.
Another subtle point is that this class seems to conflate canvases and contexts. clear is really a context operation, so the Canvas class here seems to be headed towards a combination interface of a canvas and context rolled into one. Since most canvas apps mostly work with the context and only use canvas for height/width reference, this actually creates a nice separation of concerns that abstracts the DOM/canvas away from entity classes (ball, player, enemy, etc) that are responsible for drawing themselves on an arbitrary context without needing to know about the underlying DOM object the context is from.
Long story short:
- Do you even need this? Canvases are already objects with a nice interface that may not need another layer of abstraction. If you want to abstract commonly-used drawing functions, maybe think about the entities in your app (say, a "player" entity) and create per-entity
draw functions that use a context as a parameter.
- If you do feel your design needs it, consider making the canvas itself a "private" member that isn't injected into the constructor. Instead, perhaps pass in a parent DOM element that the constructor will attach the canvas to.
Writing abstractions on the DOM without a framework like React is tricky!