import { Component, ElementRef, ViewChild } from '@angular/core'; @Component({ selector: 'amc-annotator', standalone: true, imports: [], templateUrl: './annotator.component.html', styleUrl: './annotator.component.scss' }) export class AnnotatorComponent { @ViewChild("annotator", { static: true }) public canvas!: ElementRef; private startPoint?: [number, number]; private backgroundImage?: HTMLImageElement; private isDrawing(): boolean { return this.startPoint !== undefined; } private getCanvasContext(): CanvasRenderingContext2D { const context = this.canvas.nativeElement.getContext("2d"); if (context === null) { throw new Error("canvas is not initialized"); } else { return context; } } public changeImage(image: HTMLImageElement): void { this.backgroundImage = image; this.repaintImage(); } private repaintImage(): void { const canvas = this.canvas.nativeElement; if (this.backgroundImage === undefined) { const context = this.getCanvasContext(); context.clearRect(0, 0, canvas.width, canvas.height); } else { canvas.width = this.backgroundImage.width; canvas.height = this.backgroundImage.height; const context = this.getCanvasContext(); context.clearRect(0, 0, canvas.width, canvas.height); context.drawImage(this.backgroundImage, 0, 0, canvas.width, canvas.height); } } public onMouseDown(event: MouseEvent): void { this.startPoint = [event.offsetX, event.offsetY]; } public onMouseMove(event: MouseEvent): void { if (this.isDrawing() && this.startPoint !== undefined) { const [x0, y0] = this.startPoint; const [x, y, width, height] = this.adjustCoordinates(x0, y0, event.clientX - x0, event.clientY - y0); const canvas = this.canvas.nativeElement; const context = this.getCanvasContext(); this.repaintImage(); context.globalCompositeOperation = "xor"; context.strokeStyle = "black"; context.lineWidth = Math.ceil(Math.max(canvas.width, canvas.height) / 500); context.beginPath(); context.rect(x, y, width, height); context.stroke(); } } private adjustCoordinates(x: number, y: number, width: number, height: number): [number, number, number, number] { const canvas = this.canvas.nativeElement; if (canvas.width === canvas.clientWidth && canvas.height === canvas.clientHeight) { return [x, y, width, height]; } else { return [ x * canvas.width / canvas.clientWidth, y * canvas.height / canvas.clientHeight, width * canvas.width / canvas.clientWidth, height * canvas.height / canvas.clientHeight ]; } } public onMouseUp(event: MouseEvent): void { this.startPoint = undefined; } }