export class LayeredCanvas { constructor(c) { console.log("initializeLayeredCanvas"); this.canvas = c; this.context = canvas.getContext('2d'); this.canvas.addEventListener('mousedown', this.handleMouseDown.bind(this)); this.canvas.addEventListener('mousemove', this.handleMouseMove.bind(this)); this.canvas.addEventListener('mouseup', this.handleMouseUp.bind(this)); this.canvas.addEventListener('mouseleave', this.handleMouseLeave.bind(this)); this.layers = []; } cleanup() { this.canvas.removeEventListener('mousedown', this.handleMouseDown.bind(this)); this.canvas.removeEventListener('mousemove', this.handleMouseMove.bind(this)); this.canvas.removeEventListener('mouseup', this.handleMouseUp.bind(this)); this.canvas.removeEventListener('mouseleave', this.handleMouseLeave.bind(this)); } getCanvasSize() { return [this.canvas.width, this.canvas.height]; } getCanvasPosition(event) { const rect = this.canvas.getBoundingClientRect(); const x = Math.floor(event.clientX - rect.left); const y = Math.floor(event.clientY - rect.top); return [x, y]; } handleMouseDown(event) { const p = this.getCanvasPosition(event); for (let i = this.layers.length - 1; i >= 0; i--) { const layer = this.layers[i]; if (layer.accepts(p)) { layer.mouseDown(p); this.draggingLayer = layer; this.dragStart = p; break; } } } handleMouseMove(event) { this.mouseCursor = this.getCanvasPosition(event); if (this.draggingLayer) { this.draggingLayer.mouseMove(this.getCanvasPosition(event)); // 念のため別の実体 } this.render(); } handleMouseUp(event) { if (this.draggingLayer) { this.draggingLayer.mouseUp(this.getCanvasPosition(event)); this.draggingLayer = null; } } handleMouseLeave(event) { this.mouseCursor = [-1,-1]; if (this.draggingLayer) { this.handleMouseUp(event); } } render() { for (let i = 0; i < this.layers.length; i++) { const layer = this.layers[i]; layer.render(this.canvas, this.context); } } redraw() { this.render(); } addLayer(layer) { this.layers.push(layer); } } let mouseSequence = { // mixin mouseDown(p) { this.mouseHandler = this.mouse(p); }, mouseMove(p) { if (this.mouseHandler) { this.mouseHandler.next(p); } }, mouseUp(p) { if (this.mouseHandler) { this.mouseHandler.next(null); this.mouseHandler = null; } }, /* sample mouse handler *mouse(p) { while (p = yield) { console.log("mouse", p); } } */ }; export function sequentializeMouse(layerClass) { layerClass.mouseDown = mouseSequence.mouseDown; layerClass.mouseMove = mouseSequence.mouseMove; layerClass.mouseUp = mouseSequence.mouseUp; } export class Layer { constructor() {} reserveRender() { renderReserved = true; } accepts(point) { return false; } mouseDown(point) {} mouseMove(point) {} mouseUp(point) {} render(canvas, ctx) {} }