I try to add polygon on img in canvas in angular 9 app. Found solution with javascript but can't get it to work in angular application. My mouse object is always undefined with this code
import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
import { OnChanges } from '@angular/core/src/metadata';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
@ViewChild('canvasEl') canvas: ElementRef;
private context: CanvasRenderingContext2D;
mouse = { x: 0, y: 0, button: 0, lx: 0, ly: 0, update: true };
cursor: string;
dragging: boolean;
activePoint;
poygon;
polygon: {
points: any[];
closed: boolean;
addPoint(p: any): void;
draw(): void;
drawLengthText(): void;
drawAngleText(): void;
closest(pos: any, dist?: number): any;
};
constructor() {}
ngOnInit() {
this.context = (this.canvas.nativeElement as HTMLCanvasElement).getContext(
'2d'
);
requestAnimationFrame(this.update);
['mousedown', 'mouseup', 'mousemove'].forEach((name) =>
document.addEventListener(name, (e: MouseEvent) => {
const bounds = (
this.canvas.nativeElement as HTMLCanvasElement
).getBoundingClientRect();
this.mouse.x = e.pageX - bounds.left - scrollX;
this.mouse.y = e.pageY - bounds.top - scrollY;
this.mouse.button =
e.type === 'mousedown'
? 1
: e.type === 'mouseup'
? 0
: this.mouse.button;
this.mouse.update = true;
})
);
this.context.lineWidth = 2;
this.context.strokeStyle = 'red';
const point = (x, y) => ({ x, y });
const poly = () => ({
points: [],
closed: false,
addPoint(p) {
this.points.push(point(p.x, p.y));
},
draw() {
console.log('aa' + this.mouse);
this.context.lineWidth = 2;
this.context.strokeStyle = 'red';
this.context.fillStyle = 'rgba(255, 0, 0, 0.3)';
this.context.beginPath();
for (const p of this.points) {
this.context.lineTo(p.x, p.y);
}
this.closed && this.context.closePath();
this.context.stroke();
this.closed && this.context.fill();
this.context.fillStyle = 'rgba(0, 0, 0, 0.3)';
this.context.strokeStyle = 'rgba(0, 0, 0, 0.8)';
for (const p of this.points) {
this.context.beginPath();
this.context.moveTo(p.x + 10, p.y);
this.context.arc(p.x, p.y, 10, 0, Math.PI * 2);
this.context.fill();
this.context.stroke();
}
this.points.length > 1 && this.drawLengthText();
this.points.length > 2 && this.drawAngleText();
},
drawLengthText() {
const len = this.points.length;
var p1,
i = 0;
p1 = this.points[i];
while (i < len - (this.closed ? 0 : 1)) {
const p2 = this.points[(i++ + 1) % len];
const lineLength = ((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2) ** 0.5;
this.drawLineText(p1, p2, lineLength.toFixed(0) + 'px');
if (len < 3) {
break;
}
p1 = p2;
}
this.context.setTransform(1, 0, 0, 1, 0, 0);
},
drawAngleText() {
const len = this.points.length;
var p1,
p2,
i = this.closed ? 0 : 1;
p1 = this.points[(i + len - 1) % len];
p2 = this.points[i];
while (i < len - (this.closed ? 0 : 1)) {
const p3 = this.points[(i++ + 1) % len];
this.drawAngleText(p1, p2, p3);
p1 = p2;
p2 = p3;
}
this.context.setTransform(1, 0, 0, 1, 0, 0);
},
closest(pos, dist = 8) {
var i = 0,
index = -1;
dist *= dist;
for (const p of this.points) {
var x = pos.x - p.x;
var y = pos.y - p.y;
var d2 = x * x + y * y;
if (d2 < dist) {
dist = d2;
index = i;
}
i++;
}
if (index > -1) {
return this.points[index];
}
},
});
this.polygon = poly();
}
drawCircle(pos, color = 'black', size = 8) {
this.context.strokeStyle = color;
this.context.beginPath();
this.context.arc(pos.x, pos.y, size, 0, Math.PI * 2);
this.context.stroke();
}
update() {
console.log('aaaa' + this.mouse);
if (this.mouse.update) {
this.cursor = 'crosshair';
this.context.clearRect(
0,
0,
(this.canvas.nativeElement as HTMLCanvasElement).width,
(this.canvas.nativeElement as HTMLCanvasElement).height
);
if (!this.dragging) {
this.activePoint = this.polygon.closest(this.mouse);
}
if (this.activePoint === undefined && this.mouse.button) {
this.polygon.addPoint(this.mouse);
this.mouse.button = 0;
} else if (this.activePoint) {
if (this.mouse.button) {
if (this.dragging) {
this.activePoint.x += this.mouse.x - this.mouse.lx;
this.activePoint.y += this.mouse.y - this.mouse.ly;
} else {
if (
!this.polygon.closed &&
this.polygon.points.length > 2 &&
this.activePoint === this.polygon.points[0]
) {
this.polygon.closed = true;
}
this.dragging = true;
}
} else {
this.dragging = false;
}
}
this.polygon.draw();
if (this.activePoint) {
this.drawCircle(this.activePoint);
this.cursor = 'move';
}
this.mouse.lx = this.mouse.x;
this.mouse.ly = this.mouse.y;
(this.canvas.nativeElement as HTMLCanvasElement).style.cursor =
this.cursor;
this.mouse.update = false;
}
requestAnimationFrame(this.update);
}
}
Here is where I found a solution in JS
And here is my stackblitz with whole code