@cogic/annotorious
Version:
A JavaScript image annotation library
98 lines (74 loc) • 2.8 kB
JavaScript
import RubberbandPolygon from './RubberbandPolygon';
import EditablePolygon from './EditablePolygon';
import Tool from '../Tool';
/**
* A rubberband selector for polygon fragments.
*/
export default class RubberbandPolygonTool extends Tool {
constructor(g, config, env) {
super(g, config, env);
this._isDrawing = false;
this._startOnSingleClick = false;
}
startDrawing = (x, y, startOnSingleClick) => {
this._isDrawing = true;
this._startOnSingleClick = startOnSingleClick;
this.attachListeners({
mouseMove: this.onMouseMove,
[this.config.addPolygonPointOnMouseDown && startOnSingleClick ?
'mouseDown' : 'mouseUp']: this.onMouseUpDown,
dblClick: this.onDblClick
});
this.rubberband = new RubberbandPolygon([ x, y ], this.g, this.env);
}
stop = () => {
this.detachListeners();
this._isDrawing = false;
if (this.rubberband) {
this.rubberband.destroy();
this.rubberband = null;
}
}
onMouseMove = (x, y) => {
// Constrain the initial coordinates (x, y) to be within the image bounds
const { naturalWidth, naturalHeight } = this.env.image;
const constrainX = Math.min(Math.max(x, 0), naturalWidth);
const constrainY = Math.min(Math.max(y, 0), naturalHeight);
this.rubberband.dragTo([constrainX, constrainY]);
}
onMouseUp = () => {
const { width, height } = this.rubberband.getBoundingClientRect();
const minWidth = this.config.minSelectionWidth || 4;
const minHeight = this.config.minSelectionHeight || 4;
if (width >= minWidth || height >= minHeight) {
this.rubberband.addPoint();
} else if (!this._startOnSingleClick) {
this.emit('cancel');
this.stop();
}
}
onMouseUpDown = () => {
// It seems like renaming 'onMouseUp' to 'onMouseUpDown' would be appropriate.
// However, do not do this because the 'onMouseUp' function is used in annotorious-openseadragon.
this.onMouseUp();
}
onDblClick = () => {
if (this.rubberband.points.length < (this.config.minPolygonPoints || 0)) return;
this._isDrawing = false;
const shape = this.rubberband.element;
shape.annotation = this.rubberband.toSelection();
this.emit('complete', shape);
this.stop();
}
get isDrawing() {
return this._isDrawing;
}
createEditableShape = (annotation, formatters) =>
new EditablePolygon(annotation, this.g, {...this.config, formatters}, this.env);
}
RubberbandPolygonTool.identifier = 'polygon';
RubberbandPolygonTool.supports = annotation => {
const selector = annotation.selector('SvgSelector');
if (selector)
return selector.value?.match(/^<svg.*<polygon/g);
}