Skip to content

Commit

Permalink
React UI: Improved mouse behaviour during draw/merge/edit/group/split (
Browse files Browse the repository at this point in the history
…#1130)

* Moving image with mouse during drawing, paste, group, split, merge

* Babel plugin to dev deps

* Move mouse during editing

* Minor issues
  • Loading branch information
bsekachev authored Feb 7, 2020
1 parent f800e6a commit 7d8fcfa
Show file tree
Hide file tree
Showing 7 changed files with 211 additions and 91 deletions.
6 changes: 1 addition & 5 deletions cvat-canvas/src/typescript/canvasView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -615,11 +615,7 @@ export class CanvasViewImpl implements CanvasView, Listener {

this.content.addEventListener('mousedown', (event): void => {
if ([1, 2].includes(event.which)) {
if ([Mode.DRAG_CANVAS, Mode.IDLE].includes(this.mode)) {
self.controller.enableDrag(event.clientX, event.clientY);
} else if ([Mode.ZOOM_CANVAS, Mode.DRAW].includes(this.mode) && event.which === 2) {
self.controller.enableDrag(event.clientX, event.clientY);
}
self.controller.enableDrag(event.clientX, event.clientY);
event.preventDefault();
}
});
Expand Down
156 changes: 104 additions & 52 deletions cvat-canvas/src/typescript/drawHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');

Expand Down Expand Up @@ -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);

Expand All @@ -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,
});
}

Expand All @@ -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
Expand All @@ -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) {
Expand All @@ -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;
});
Expand Down Expand Up @@ -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)
Expand All @@ -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);
});
}

Expand Down Expand Up @@ -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();
Expand All @@ -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);
});
}

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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();
}
}

Expand Down
Loading

0 comments on commit 7d8fcfa

Please sign in to comment.