@recogito/annotorious
Advanced tools
Comparing version 2.0.0-alpha to 2.0.1-alpha
{ | ||
"name": "@recogito/annotorious", | ||
"version": "2.0.0-alpha", | ||
"version": "2.0.1-alpha", | ||
"description": "A JavaScript image annotation library", | ||
@@ -41,3 +41,3 @@ "main": "src/index.js", | ||
"dependencies": { | ||
"@recogito/recogito-client-core": "^0.1.1", | ||
"@recogito/recogito-client-core": "^0.1.2", | ||
"axios": "^0.19.2", | ||
@@ -44,0 +44,0 @@ "react": "^16.13.1", |
@@ -20,3 +20,3 @@ # Annotorious 2 | ||
```html | ||
<script src="annotorious-2.0.0-alpha.min.js"></script> | ||
<script src="annotorious-2.0.1-alpha.min.js"></script> | ||
``` | ||
@@ -42,3 +42,3 @@ | ||
</script> | ||
<script type="text/javascript" src="annotorious-2.0.0-alpha.min.js"></script> | ||
<script type="text/javascript" src="annotorious-2.0.1-alpha.min.js"></script> | ||
</body> | ||
@@ -45,0 +45,0 @@ ``` |
@@ -6,4 +6,2 @@ import EventEmitter from 'tiny-emitter'; | ||
import './AnnotationLayer.scss'; | ||
export default class AnnotationLayer extends EventEmitter { | ||
@@ -45,3 +43,3 @@ | ||
_addAnnotation = annotation => { | ||
addAnnotation = annotation => { | ||
const g = drawRect(annotation); | ||
@@ -54,18 +52,50 @@ g.setAttribute('class', 'a9s-annotation'); | ||
g.addEventListener('mouseenter', () => | ||
this.currentHover = g); | ||
g.addEventListener('mouseenter', evt => { | ||
if (this.currentHover !== g) | ||
this.emit('mouseEnterAnnotation', annotation, evt); | ||
this.currentHover = g; | ||
}); | ||
g.addEventListener('mouseleave', () => | ||
this.currentHover = null); | ||
g.addEventListener('mouseleave', evt => { | ||
if (this.currentHover === g) | ||
this.emit('mouseLeaveAnnotation', annotation, evt); | ||
this.currentHover = null; | ||
}); | ||
return g; | ||
} | ||
_findShape = annotation => | ||
this.svg.querySelector(`.a9s-annotation[data-id="${annotation.id}"]`); | ||
findShape = annotationOrId => { | ||
const id = annotationOrId.id ? annotationOrId.id : annotationOrId; | ||
return this.svg.querySelector(`.a9s-annotation[data-id="${id}"]`); | ||
} | ||
/** | ||
* Redraws the whole layer with annotations sorted by | ||
* size, so that larger ones don't occlude smaller ones. | ||
*/ | ||
redraw = () => { | ||
const shapes = Array.from(this.svg.querySelectorAll('.a9s-annotation')); | ||
const annotations = shapes.map(s => s.annotation); | ||
annotations.sort((a, b) => rectArea(b) - rectArea(a)); | ||
// Clear the SVG element | ||
shapes.forEach(s => this.svg.removeChild(s)); | ||
// Redraw | ||
annotations.forEach(this.addAnnotation); | ||
} | ||
clearSelection = () => | ||
this.currentTool.clear(); | ||
/****************/ | ||
/* External API */ | ||
/****************/ | ||
init = annotations => { | ||
// Sort annotations by size | ||
annotations.sort((a, b) => rectArea(b) - rectArea(a)); | ||
annotations.forEach(this._addAnnotation); | ||
annotations.forEach(this.addAnnotation); | ||
} | ||
@@ -77,3 +107,3 @@ | ||
this._addAnnotation(annotation); | ||
this.addAnnotation(annotation); | ||
@@ -85,3 +115,3 @@ // Make sure rendering order is large-to-small | ||
removeAnnotation = annotation => { | ||
const shape = this._findShape(annotation); | ||
const shape = this.findShape(annotation); | ||
if (shape) | ||
@@ -96,21 +126,25 @@ shape.parentNode.removeChild(shape); | ||
/** | ||
* Redraws the whole layer with annotations sorted by | ||
* size, so that larger ones don't occlude smaller ones. | ||
*/ | ||
redraw = () => { | ||
const shapes = Array.from(this.svg.querySelectorAll('.a9s-annotation')); | ||
const annotations = shapes.map(s => s.annotation); | ||
annotations.sort((a, b) => rectArea(b) - rectArea(a)); | ||
setAnnotationsVisible = visible => { | ||
if (visible) | ||
this.svg.style.display = null; | ||
else | ||
this.svg.style.display = 'none'; | ||
} | ||
// Clear the SVG element | ||
shapes.forEach(s => this.svg.removeChild(s)); | ||
selectAnnotation = annotationOrId => { | ||
const selected = this.findShape(annotationOrId); | ||
if (selected) { | ||
this.emit('select', { | ||
selection: selected.annotation, | ||
bounds: selected.getBoundingClientRect() | ||
}); | ||
} | ||
} | ||
// Redraw | ||
annotations.forEach(this._addAnnotation); | ||
destroy = () => { | ||
this.currentTool = null; | ||
this.currentHover = null; | ||
this.svg.parentNode.removeChild(this.svg); | ||
} | ||
clearSelection = () => | ||
this.currentTool.clear(); | ||
} |
@@ -24,2 +24,3 @@ import React, { Component } from 'react'; | ||
this.annotationLayer = new AnnotationLayer(this.props.wrapperEl); | ||
this.annotationLayer.on('select', evt => this.setState({ | ||
@@ -29,4 +30,11 @@ selectedAnnotation: evt.selection, | ||
})); | ||
this.annotationLayer.on('mouseEnterAnnotation', this.props.onMouseEnterAnnotation); | ||
this.annotationLayer.on('mouseLeaveAnnotation', this.props.onMouseLeaveAnnotation); | ||
} | ||
componentWillUnmount() { | ||
this.annotationLayer.destroy(); | ||
} | ||
/**************************/ | ||
@@ -86,9 +94,20 @@ /* Annotation CRUD events */ | ||
setAnnotationsVisible = visible => | ||
this.annotationLayer.setAnnotationsVisible(visible); | ||
selectAnnotation = arg => { | ||
if (arg) | ||
this.annotationLayer.selectAnnotation(arg); | ||
else | ||
// Deselect | ||
this.clearState(); | ||
} | ||
render() { | ||
return (this.state.selectedAnnotation && ( | ||
<Editor | ||
readOnly={this.props.readOnly} | ||
wrapperEl={this.props.wrapperEl} | ||
bounds={this.state.selectionBounds} | ||
wrapperEl={this.props.wrapperEl} | ||
annotation={this.state.selectedAnnotation} | ||
readOnly={this.props.readOnly} | ||
onAnnotationCreated={this.onCreateOrUpdateAnnotation('onAnnotationCreated')} | ||
@@ -95,0 +114,0 @@ onAnnotationUpdated={this.onCreateOrUpdateAnnotation('onAnnotationUpdated')} |
@@ -37,4 +37,4 @@ import React from 'react'; | ||
const appContainerEl = document.createElement('DIV'); | ||
wrapperEl.appendChild(appContainerEl); | ||
this._appContainerEl = document.createElement('DIV'); | ||
wrapperEl.appendChild(this._appContainerEl); | ||
@@ -49,5 +49,8 @@ const { CommentWidget, TagWidget } = Editor; | ||
wrapperEl={wrapperEl} | ||
readOnly={config.readOnly} | ||
onAnnotationCreated={this.handleAnnotationCreated} | ||
onAnnotationUpdated={this.handleAnnotationUpdated} | ||
onAnnotationDeleted={this.handleAnnotationDeleted}> | ||
onAnnotationDeleted={this.handleAnnotationDeleted} | ||
onMouseEnterAnnotation={this.handleMouseEnterAnnotation} | ||
onMouseLeaveAnnotation={this.handleMouseLeaveAnnotation}> | ||
@@ -59,13 +62,19 @@ <CommentWidget /> | ||
appContainerEl); | ||
this._appContainerEl); | ||
} | ||
handleAnnotationCreated = annotation => | ||
this._emitter.emit('createAnnotation', annotation); | ||
this._emitter.emit('createAnnotation', annotation.underlying); | ||
handleAnnotationUpdated = (annotation, previous) => | ||
this._emitter.emit('updateAnnotation', annotation, previous); | ||
this._emitter.emit('updateAnnotation', annotation.underlying, previous.underlying); | ||
handleAnnotationDeleted = annotation => | ||
this._emitter.emit('deleteAnnotation', annotation); | ||
this._emitter.emit('deleteAnnotation', annotation.underlying); | ||
handleMouseEnterAnnotation = (annotation, evt) => | ||
this._emitter.emit('mouseEnterAnnotation', annotation.underlying, evt); | ||
handleMouseLeaveAnnotation = (annotation, evt) => | ||
this._emitter.emit('mouseLeaveAnnotation', annotation.underlying, evt); | ||
@@ -77,3 +86,3 @@ /******************/ | ||
/** | ||
* Adds a JSON-LD WebAnnotation to the annotation layer. | ||
* Adds a single JSON-LD WebAnnotation to the annotation layer. | ||
*/ | ||
@@ -98,8 +107,34 @@ addAnnotation = annotation => | ||
/** Initializes the annotation layer with the list of WebAnnotations **/ | ||
setAnnotations = annotations => { | ||
const webannotations = annotations.map(a => new WebAnnotation(a)); | ||
this._app.current.setAnnotations(webannotations); | ||
} | ||
/** | ||
* Returns all annotations | ||
*/ | ||
getAnnotations = () => | ||
this._app.current.getAnnotations(); | ||
getAnnotations = () => { | ||
const annotations = this._app.current.getAnnotations(); | ||
return annotations.map(a => a._annotation); | ||
} | ||
/** Shows or hides the annotation layer **/ | ||
setAnnotationsVisible = visible => | ||
this._app.current.setAnnotationsVisible(visible); | ||
/** Programmatically selects the annotation, opening the editor popup **/ | ||
selectAnnotation = annotationOrId => { | ||
const arg = (annotationOrId?.type === 'Annotation') ? | ||
new WebAnnotation(annotationOrId) : annotationOrId; | ||
this._app.current.selectAnnotation(arg); | ||
} | ||
/** | ||
* Unmounts the annotator component | ||
*/ | ||
destroy = () => | ||
ReactDOM.unmountComponentAtNode(this._appContainerEl); | ||
/** | ||
@@ -106,0 +141,0 @@ * Adds an event handler. |
@@ -11,2 +11,3 @@ import { Selection } from '@recogito/recogito-client-core'; | ||
this.shape = drawRect(anchorX, anchorY, 2, 2); | ||
this.shape.setAttribute('class', 'a9s-selection'); | ||
@@ -28,4 +29,4 @@ // We make this shape transparent to pointer events | ||
y: h > 0 ? this.anchor[1] : this.opposite[1], | ||
w: Math.abs(w), | ||
h: Math.abs(h) | ||
w: Math.max(1, Math.abs(w)), // Negative values | ||
h: Math.max(1, Math.abs(h)) | ||
}; | ||
@@ -32,0 +33,0 @@ } |
import EventEmitter from 'tiny-emitter'; | ||
import DraggableRect from './DraggableRect'; | ||
import './RectDragSelector.scss'; | ||
export class RectDragSelector extends EventEmitter { | ||
@@ -7,0 +5,0 @@ |
@@ -13,3 +13,3 @@ const path = require('path'); | ||
output: { | ||
filename: 'annotorious-2.0.0-alpha.min.js', | ||
filename: 'annotorious-2.0.1-alpha.min.js', | ||
library: 'Annotorious', | ||
@@ -16,0 +16,0 @@ libraryTarget: 'umd', |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
102620
543
15