I have a component that has a canvas on it, covered exactly by a mapped image. Based on mouse movement on top of the image, I highlight or unhighlight part of the canvas. I had intended to have multiple components like this, each independent from one another, one after another on my page, repeated vertically (so, the "upper" canvas is the one closer to the top of the page, whereas the "lower" canvas is the one after it)
The problem is that events on the bottom image map only affect the first canvas (i.e. if I mouseover the correct area on the second canvas, then the first canvas is the one that gets drawn on). I want it so that each component is independent - if I do something on the second component, it should affect the second canvas and not the first canvas.
In other words, Both components are sharing the first component's canvas, instead of each using their own canvases. This is a problem.
Here's an MCVE:
dummy-component.html:
<div style="position: relative; display: inline-block; width: 520px; height: 160px; background-color: green">
<canvas #myCanvas width="520" height="160"
style="position: absolute; left: 0; top: 0; background-color: green; user-select: none"></canvas>
<img #mapOverlay width="520" height="160"
style="position: absolute; left: 0; top: 0; background-color: transparent; user-select: none"
usemap="#overlay">
<map #overlay id="overlay" name="overlay">
<area shape="rect" coords="0, 0, 259, 159"
(mouseover)="hover()" (mouseout)="unhover()" (click)="drawSmiley()">
</map>
</div>
dummy-component.ts:
@Component({
selector: 'app-dummy',
templateUrl: './dummy.component.html',
})
export class DummyComponent implements AfterViewInit {
@ViewChild('myCanvas') private myCanvasElement!: ElementRef<HTMLCanvasElement>
private myCanvas!: CanvasRenderingContext2D;
private smileyFace: HTMLImageElement = new Image();
constructor() { this.smileyFace.src = "assets/smiley.png"; }
ngAfterViewInit(): void {
this.myCanvas = <CanvasRenderingContext2D> this.myCanvasElement.nativeElement.getContext('2d');
}
hover() {
this.myCanvas.clearRect(0, 0, 520, 160);
this.myCanvas.fillStyle = "#ffffff33"; // draw transparent highlight
this.myCanvas.fillRect(0, 0, 260, 160);
}
unhover() { this.myCanvas.clearRect(0, 0, 520, 160); }
drawSmiley() { this.myCanvas.drawImage(this.smileyFace, 15, 15); }
}
app-component.html:
<div>
<app-dummy></app-dummy>
<app-dummy></app-dummy>
</div>
The first canvas's requisite events also affect the first canvas, fwiw.
I can't find any questions about this, or guides on how to accomplish this - Angular's documentation for @ViewChild says that "The change detector looks for the first element or the directive matching the selector in the view DOM", and that's probably related (I suspect the second element is borrowing the first element's @ViewChild and also using it for itself), but I don't know how to apply that information and make it stick to its own canvas.