Странное поведение при повторной отрисовке прямоугольника в классе JS
Первый раз пытаюсь работать с ООП, пытаюсь создать класс который будет рисовать на canvas. Почему при повторном выполнении метода drawRect() прямоугольник рисуется на половину canvas? Объясните это странное поведение.
Ссылка на codepen: https://codepen.io/ilyacnt/pen/KKZzzRL
class CanvasRenderer {
canvasElement = null;
canvasWidth = 0;
canvasHeight = 0;
ctx = null;
constructor(canvasElement) {
this.canvasElement = canvasElement;
this.ctx = canvasElement.getContext("2d");
this.canvasHeight = canvasElement.height;
this.canvasWidth = canvasElement.width;
}
clear() {
this.ctx.rect(0, 0, this.canvasHeight, this.canvasWidth);
this.ctx.fillStyle = "white";
this.ctx.fill();
}
}
class Brush extends CanvasRenderer {
currentFillColor = "black";
constructor(canvasElement) {
super(canvasElement);
}
set fillColor(color) {
this.currentFillColor = color;
}
drawRect() {
this.ctx.fillStyle = this.currentFillColor;
this.ctx.rect(450, 300, 50, 50);
this.ctx.fill();
}
}
const canvasElement = document.getElementById("canvas");
const brush = new Brush(canvasElement);
brush.drawRect();
brush.clear();
brush.drawRect();
<canvas id="canvas"></canvas>
Ответы (1 шт):
Прямоугольник рисуется на всю ширину и всю высоту, потому что в CanvasRenderer.clear() создаётся контур прямоугольника (rect), который заливается в последующих вызовах fill.
Перед новой заливкой (fill) или выделения контуров (stroke) нужно вызвать beginPath, чтобы эти действия применялись к ожидаемым очертаниям:
class CanvasRenderer {
canvasElement = null;
canvasWidth = 0;
canvasHeight = 0;
ctx = null;
constructor(canvasElement) {
this.canvasElement = canvasElement;
this.ctx = canvasElement.getContext("2d");
this.canvasHeight = canvasElement.height;
this.canvasWidth = canvasElement.width;
}
clear() {
this.ctx.beginPath();
this.ctx.rect(0, 0, this.canvasHeight, this.canvasWidth);
this.ctx.fillStyle = "white";
this.ctx.fill();
}
}
class Brush extends CanvasRenderer {
currentFillColor = "black";
constructor(canvasElement) {
super(canvasElement);
}
set fillColor(color) {
this.currentFillColor = color;
}
drawRect() {
this.ctx.beginPath();
this.ctx.fillStyle = this.currentFillColor;
this.ctx.rect(450, 300, 50, 50);
this.ctx.fill();
}
}
const canvasElement = document.getElementById("canvas");
const brush = new Brush(canvasElement);
brush.drawRect();
brush.clear();
brush.drawRect();
<canvas id="canvas" width="900" height="600"></canvas>
Также можно использовать готовые решения для заливки (fillRect) и очистки (clearRect) прямоугольников:
class CanvasRenderer {
canvasElement = null;
canvasWidth = 0;
canvasHeight = 0;
ctx = null;
constructor(canvasElement) {
this.canvasElement = canvasElement;
this.ctx = canvasElement.getContext("2d");
this.canvasHeight = canvasElement.height;
this.canvasWidth = canvasElement.width;
}
clear() {
this.ctx.clearRect(0, 0, this.canvasHeight, this.canvasWidth);
}
}
class Brush extends CanvasRenderer {
currentFillColor = "black";
constructor(canvasElement) {
super(canvasElement);
}
set fillColor(color) {
this.currentFillColor = color;
}
drawRect() {
this.ctx.fillStyle = this.currentFillColor;
this.ctx.fillRect(450, 300, 50, 50);
}
}
const canvasElement = document.getElementById("canvas");
const brush = new Brush(canvasElement);
brush.drawRect();
brush.clear();
brush.drawRect();
<canvas id="canvas" width="900" height="600"></canvas>