class Drawing extends Canvas { mouseRasterX = -1; mouseRasterY = -1; color0 = "#00F"; color1 = "#FFF"; constructor(rasterCountWidth, rasterCountHeight, size, canvasElementId) { super(canvasElementId, rasterCountWidth * size, rasterCountHeight * size, (event) => this.mouseEvent(event)); this.size = size; this.matrix = new Array(rasterCountHeight).fill(0).map(() => new Array(rasterCountWidth).fill(undefined)); this.draw(); } mouseEvent(event) { this.updateCursor(event); this.mouseDraw(event); this.draw(); } mouseDraw(event) { let color; if (Boolean(event.buttons & 1)) { color = this.color0; } else if (Boolean(event.buttons & 2)) { color = undefined; } else { return; } this.matrix[this.mouseRasterY][this.mouseRasterX] = color; } updateCursor(event) { this.mouseRasterX = Math.floor(event.offsetX / this.size); this.mouseRasterY = Math.floor(event.offsetY / this.size); } draw() { this.ctx.fillStyle = "#fff"; this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); this.drawMatrix(); this.drawRaster(0, 0, this.canvas.width, this.canvas.height, this.size, this.size); } drawMatrix() { for (let y = 0; y < this.matrix.length; y++) { const row = this.matrix[y]; for (let x = 0; x < row.length; x++) { const color = row[x]; if (color === undefined) { continue; } this.ctx.beginPath(); this.ctx.fillStyle = color; this.ctx.rect(x * this.size, y * this.size, this.size, this.size); this.ctx.fill(); } } } drawRaster(xBgn, yBgn, w, h, rx, ry) { const xEnd = xBgn + w; const yEnd = yBgn + h; this.ctx.beginPath(); for (let x = xBgn; x <= xEnd; x += rx) { this.ctx.moveTo(x, yBgn); this.ctx.lineTo(x, yEnd); } for (let y = yBgn; y <= yEnd; y += ry) { this.ctx.moveTo(xBgn, y); this.ctx.lineTo(xEnd, y); } this.ctx.strokeStyle = "#aaa"; this.ctx.stroke(); if (this.mouseRasterX >= 0) { this.ctx.beginPath(); this.ctx.strokeStyle = "blue"; this.ctx.rect(this.mouseRasterX * this.size, this.mouseRasterY * this.size, this.size, this.size); this.ctx.stroke(); } } }