|
|
|
|
@ -115,6 +115,7 @@ export class DrawHandlerImpl implements DrawHandler {
|
|
|
|
|
|
|
|
|
|
private release(): void {
|
|
|
|
|
this.canvas.off('mousedown.draw');
|
|
|
|
|
this.canvas.off('mouseup.draw');
|
|
|
|
|
this.canvas.off('mousemove.draw');
|
|
|
|
|
this.canvas.off('click.draw');
|
|
|
|
|
|
|
|
|
|
@ -179,14 +180,7 @@ export class DrawHandlerImpl implements DrawHandler {
|
|
|
|
|
|
|
|
|
|
private drawBox(): void {
|
|
|
|
|
this.drawInstance = this.canvas.rect();
|
|
|
|
|
this.drawInstance.draw({
|
|
|
|
|
snapToGrid: 0.1,
|
|
|
|
|
}).addClass('cvat_canvas_shape_drawing').attr({
|
|
|
|
|
'stroke-width': consts.BASE_STROKE_WIDTH / this.geometry.scale,
|
|
|
|
|
z_order: Number.MAX_SAFE_INTEGER,
|
|
|
|
|
}).on('drawupdate', (): void => {
|
|
|
|
|
this.shapeSizeElement.update(this.drawInstance);
|
|
|
|
|
}).on('drawstop', (e: Event): void => {
|
|
|
|
|
this.drawInstance.on('drawstop', (e: Event): void => {
|
|
|
|
|
const bbox = (e.target as SVGRectElement).getBBox();
|
|
|
|
|
const [xtl, ytl, xbr, ybr] = this.getFinalRectCoordinates(bbox);
|
|
|
|
|
|
|
|
|
|
@ -198,6 +192,11 @@ export class DrawHandlerImpl implements DrawHandler {
|
|
|
|
|
} else {
|
|
|
|
|
this.onDrawDone(null);
|
|
|
|
|
}
|
|
|
|
|
}).on('drawupdate', (): void => {
|
|
|
|
|
this.shapeSizeElement.update(this.drawInstance);
|
|
|
|
|
}).addClass('cvat_canvas_shape_drawing').attr({
|
|
|
|
|
'stroke-width': consts.BASE_STROKE_WIDTH / this.geometry.scale,
|
|
|
|
|
z_order: Number.MAX_SAFE_INTEGER,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -213,25 +212,20 @@ export class DrawHandlerImpl implements DrawHandler {
|
|
|
|
|
}
|
|
|
|
|
}.bind(this);
|
|
|
|
|
|
|
|
|
|
const sizeIncrement = function sizeIncrement(): void {
|
|
|
|
|
size++;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (this.drawData.numberOfPoints) {
|
|
|
|
|
this.drawInstance.on('drawstart', sizeDecrement);
|
|
|
|
|
this.drawInstance.on('drawpoint', sizeDecrement);
|
|
|
|
|
this.drawInstance.on('undopoint', sizeIncrement);
|
|
|
|
|
this.drawInstance.on('undopoint', (): number => size++);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add ability to cancel the latest drawn point
|
|
|
|
|
const handleUndo = function handleUndo(e: MouseEvent): void {
|
|
|
|
|
this.canvas.on('mousedown.draw', (e: MouseEvent): void => {
|
|
|
|
|
if (e.which === 3) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
this.drawInstance.draw('undo');
|
|
|
|
|
}
|
|
|
|
|
}.bind(this);
|
|
|
|
|
this.canvas.on('mousedown.draw', handleUndo);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Add ability to draw shapes by sliding
|
|
|
|
|
// We need to remember last drawn point
|
|
|
|
|
@ -244,7 +238,7 @@ export class DrawHandlerImpl implements DrawHandler {
|
|
|
|
|
y: null,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleSlide = function handleSlide(e: MouseEvent): void {
|
|
|
|
|
this.canvas.on('mousemove.draw', (e: MouseEvent): void => {
|
|
|
|
|
// TODO: Use enumeration after typification cvat-core
|
|
|
|
|
if (e.shiftKey && ['polygon', 'polyline'].includes(this.drawData.shapeType)) {
|
|
|
|
|
if (lastDrawnPoint.x === null || lastDrawnPoint.y === null) {
|
|
|
|
|
@ -259,14 +253,15 @@ export class DrawHandlerImpl implements DrawHandler {
|
|
|
|
|
this.drawInstance.draw('point', e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
}
|
|
|
|
|
}.bind(this);
|
|
|
|
|
this.canvas.on('mousemove.draw', handleSlide);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// We need scale just drawn points
|
|
|
|
|
const self = this;
|
|
|
|
|
this.drawInstance.on('drawstart drawpoint', (e: CustomEvent): void => {
|
|
|
|
|
self.transform(self.geometry);
|
|
|
|
|
this.transform(this.geometry);
|
|
|
|
|
lastDrawnPoint.x = e.detail.event.clientX;
|
|
|
|
|
lastDrawnPoint.y = e.detail.event.clientY;
|
|
|
|
|
});
|
|
|
|
|
@ -307,39 +302,36 @@ export class DrawHandlerImpl implements DrawHandler {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private drawPolygon(): void {
|
|
|
|
|
this.drawInstance = (this.canvas as any).polygon().draw({
|
|
|
|
|
snapToGrid: 0.1,
|
|
|
|
|
}).addClass('cvat_canvas_shape_drawing').attr({
|
|
|
|
|
'stroke-width': consts.BASE_STROKE_WIDTH / this.geometry.scale,
|
|
|
|
|
});
|
|
|
|
|
this.drawInstance = (this.canvas as any).polygon()
|
|
|
|
|
.addClass('cvat_canvas_shape_drawing').attr({
|
|
|
|
|
'stroke-width': consts.BASE_STROKE_WIDTH / this.geometry.scale,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.drawPolyshape();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private drawPolyline(): void {
|
|
|
|
|
this.drawInstance = (this.canvas as any).polyline().draw({
|
|
|
|
|
snapToGrid: 0.1,
|
|
|
|
|
}).addClass('cvat_canvas_shape_drawing').attr({
|
|
|
|
|
'stroke-width': consts.BASE_STROKE_WIDTH / this.geometry.scale,
|
|
|
|
|
'fill-opacity': 0,
|
|
|
|
|
});
|
|
|
|
|
this.drawInstance = (this.canvas as any).polyline()
|
|
|
|
|
.addClass('cvat_canvas_shape_drawing').attr({
|
|
|
|
|
'stroke-width': consts.BASE_STROKE_WIDTH / this.geometry.scale,
|
|
|
|
|
'fill-opacity': 0,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.drawPolyshape();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private drawPoints(): void {
|
|
|
|
|
this.drawInstance = (this.canvas as any).polygon().draw({
|
|
|
|
|
snapToGrid: 0.1,
|
|
|
|
|
}).addClass('cvat_canvas_shape_drawing').attr({
|
|
|
|
|
'stroke-width': 0,
|
|
|
|
|
opacity: 0,
|
|
|
|
|
});
|
|
|
|
|
this.drawInstance = (this.canvas as any).polygon()
|
|
|
|
|
.addClass('cvat_canvas_shape_drawing').attr({
|
|
|
|
|
'stroke-width': 0,
|
|
|
|
|
opacity: 0,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.drawPolyshape();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private pastePolyshape(): void {
|
|
|
|
|
this.canvas.on('click.draw', (e: MouseEvent): void => {
|
|
|
|
|
this.drawInstance.on('done', (e: CustomEvent): void => {
|
|
|
|
|
const targetPoints = this.drawInstance
|
|
|
|
|
.attr('points')
|
|
|
|
|
.split(/[,\s]/g)
|
|
|
|
|
@ -355,7 +347,7 @@ export class DrawHandlerImpl implements DrawHandler {
|
|
|
|
|
attributes: { ...this.drawData.initialState.attributes },
|
|
|
|
|
label: this.drawData.initialState.label,
|
|
|
|
|
color: this.drawData.initialState.color,
|
|
|
|
|
}, e.ctrlKey);
|
|
|
|
|
}, e.detail.originalEvent.ctrlKey);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -384,7 +376,7 @@ export class DrawHandlerImpl implements DrawHandler {
|
|
|
|
|
});
|
|
|
|
|
this.pasteShape();
|
|
|
|
|
|
|
|
|
|
this.canvas.on('click.draw', (e: MouseEvent): void => {
|
|
|
|
|
this.drawInstance.on('done', (e: CustomEvent): void => {
|
|
|
|
|
const bbox = this.drawInstance.node.getBBox();
|
|
|
|
|
const [xtl, ytl, xbr, ybr] = this.getFinalRectCoordinates(bbox);
|
|
|
|
|
this.release();
|
|
|
|
|
@ -396,7 +388,7 @@ export class DrawHandlerImpl implements DrawHandler {
|
|
|
|
|
attributes: { ...this.drawData.initialState.attributes },
|
|
|
|
|
label: this.drawData.initialState.label,
|
|
|
|
|
color: this.drawData.initialState.color,
|
|
|
|
|
}, e.ctrlKey);
|
|
|
|
|
}, e.detail.originalEvent.ctrlKey);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -463,6 +455,60 @@ export class DrawHandlerImpl implements DrawHandler {
|
|
|
|
|
this.pastePolyshape();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private setupPasteEvents(): void {
|
|
|
|
|
let mouseX: number | null = null;
|
|
|
|
|
let mouseY: number | null = null;
|
|
|
|
|
|
|
|
|
|
this.canvas.on('mousedown.draw', (e: MouseEvent): void => {
|
|
|
|
|
if (e.which === 1) {
|
|
|
|
|
mouseX = e.clientX;
|
|
|
|
|
mouseY = e.clientY;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.canvas.on('mouseup.draw', (e: MouseEvent): void => {
|
|
|
|
|
const threshold = 10; // px
|
|
|
|
|
if (e.which === 1) {
|
|
|
|
|
if (Math.sqrt( // l2 distance < threshold
|
|
|
|
|
((mouseX - e.clientX) ** 2)
|
|
|
|
|
+ ((mouseY - e.clientY) ** 2),
|
|
|
|
|
) < threshold) {
|
|
|
|
|
this.drawInstance.fire('done', { originalEvent: e });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private setupDrawEvents(): void {
|
|
|
|
|
let initialized = false;
|
|
|
|
|
let mouseX: number | null = null;
|
|
|
|
|
let mouseY: number | null = null;
|
|
|
|
|
|
|
|
|
|
this.canvas.on('mousedown.draw', (e: MouseEvent): void => {
|
|
|
|
|
if (e.which === 1) {
|
|
|
|
|
mouseX = e.clientX;
|
|
|
|
|
mouseY = e.clientY;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.canvas.on('mouseup.draw', (e: MouseEvent): void => {
|
|
|
|
|
const threshold = 10; // px
|
|
|
|
|
if (e.which === 1) {
|
|
|
|
|
if (Math.sqrt( // l2 distance < threshold
|
|
|
|
|
((mouseX - e.clientX) ** 2)
|
|
|
|
|
+ ((mouseY - e.clientY) ** 2),
|
|
|
|
|
) < threshold) {
|
|
|
|
|
if (!initialized) {
|
|
|
|
|
this.drawInstance.draw(e, { snapToGrid: 0.1 });
|
|
|
|
|
initialized = true;
|
|
|
|
|
} else {
|
|
|
|
|
this.drawInstance.draw(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private startDraw(): void {
|
|
|
|
|
// TODO: Use enums after typification cvat-core
|
|
|
|
|
if (this.drawData.initialState) {
|
|
|
|
|
@ -490,16 +536,22 @@ export class DrawHandlerImpl implements DrawHandler {
|
|
|
|
|
this.pastePoints(stringifiedPoints);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (this.drawData.shapeType === 'rectangle') {
|
|
|
|
|
this.drawBox();
|
|
|
|
|
// Draw instance was initialized after drawBox();
|
|
|
|
|
this.shapeSizeElement = displayShapeSize(this.canvas, this.text);
|
|
|
|
|
} else if (this.drawData.shapeType === 'polygon') {
|
|
|
|
|
this.drawPolygon();
|
|
|
|
|
} else if (this.drawData.shapeType === 'polyline') {
|
|
|
|
|
this.drawPolyline();
|
|
|
|
|
} else if (this.drawData.shapeType === 'points') {
|
|
|
|
|
this.drawPoints();
|
|
|
|
|
|
|
|
|
|
this.setupPasteEvents();
|
|
|
|
|
} else {
|
|
|
|
|
if (this.drawData.shapeType === 'rectangle') {
|
|
|
|
|
this.drawBox();
|
|
|
|
|
// Draw instance was initialized after drawBox();
|
|
|
|
|
this.shapeSizeElement = displayShapeSize(this.canvas, this.text);
|
|
|
|
|
} else if (this.drawData.shapeType === 'polygon') {
|
|
|
|
|
this.drawPolygon();
|
|
|
|
|
} else if (this.drawData.shapeType === 'polyline') {
|
|
|
|
|
this.drawPolyline();
|
|
|
|
|
} else if (this.drawData.shapeType === 'points') {
|
|
|
|
|
this.drawPoints();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.setupDrawEvents();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|