Annotating An Image In JavaScript – Annotorious

Category: Image , Javascript , Recommended | April 4, 2021
Author: recogito
Views Total: 135 views
Official Page: Go to website
Last Update: April 4, 2021
License: BSD-3-Clause


Annotating An Image In JavaScript – Annotorious


Annotorious is a simple yet feature-rich JavaScript image annotation library that adds custom comments, notes, tags to a specific part of an image.


  • Load pre-defined annotations from a JSON file.
  • Drag and drop to create new annotations from an editor popup.
  • Based on W3C WebAnnotation model.
  • Touch & Mobile friendly.

How to use it:

1. Install and import the Annotorious as a module.

$ npm install @recogito/annotorious --save
import { Annotorious } from '@recogito/annotorious';

2. Or download the package and insert the annotorious.min.js into the HTML document.

<link rel="annotorious.min.css" href="styles.css" />
<script src="annotorious.min.js"></script>

3. Initialize the Annotorious on the image and we’re ready to go.

<img id="example" src="example.jpg" />
var anno = Annotorious.init({
    image: 'example'

4. Define your annotations in a w3c.json file and load it on page load.

// annotations.w3c.json
    "@context": "",
    "id": "#unique-ID-Here",
    "type": "Annotation",
    "body": [{
      "type": "TextualBody",
      "value": "Comments Here"
    }, {
      "type": "TextualBody",
      "purpose": "tagging",
      "value": "Tag 1"
    }, {
      "type": "TextualBody",
      "purpose": "tagging",
      "value": "Tag 2"
    "target": {
      "selector": [{
        "type": "FragmentSelector",
        "conformsTo": "",
        "value": "xywh=pixel:270,120,90,170"

3. Enable read-only mode. Defaults to false.

var anno = Annotorious.init({
    image: 'example',
    readOnly: true

4. Disable the editor popup. Defaults to false.

var anno = Annotorious.init({
    image: 'example',
    disableEditor: true

5. Add a new annotation to the image following the structure you’ve seen in the annotations.w3c.json.

// add an annotation
anno.addAnnotation(annotation [, readOnly]);

// add an array of annotations

6. Remove an annotation from the image.


7. Get all annotations.


8. Select an annotation.

// select the current annotation

// select a specific annotation

9. Show/hide the annotations.


10. Apply a custom template to the annotation.

anno.applyTemplate(template, openEditor[TRUE/FALSE]);

11. Set & get author info.

// set
  id: '',
  displayName: 'CSSScript'
// clear

12. Switch between drawing tools: ‘rect’ or ‘polygon’.


13. Show or hide the annotation layer.


14. Set a server time timestamp.


15. Destroy the instance.


16. Event handlers.

anno.on('changeSelectionTarget', function(target) {
  // when the shape of a newly created selection

anno.on('createSelection', function(selection) {
  // when a new selection shape is drawn on the image

anno.on('cancelSelection', function(selection) {
  // do something

anno.on('selectAnnotation', function(annotation) {
  console.log('selected', annotation);

anno.on('createAnnotation', function(a) {
  console.log('created', a);

anno.on('updateAnnotation', function(annotation, previous) {
  console.log('updated', previous, 'with', annotation);

anno.on('deleteAnnotation', function(annotation) {
  console.log('deleted', annotation);

anno.on('mouseEnterAnnotation', function(annotation, event) {
  console.log('mouseEnter', annotation);

anno.on('mouseLeaveAnnotation', function(annotation, event) {
  console.log('mouseLeave', annotation);

17. Use custom formater function:

// String Example
var formatter = function(annotation) {
    var longComments = annotation.bodies.filter(function(body) {
      var isComment = body.type === 'TextualBody' && 
        (body.purpose === 'commenting' || body.purpose === 'replying');
      var isLong = body.value.length > 100;
      return isComment && isLong;
    if (longComments.length > 0) {
      // This annotation contains long comments - add CSS class
      return 'long';
var anno = Annotorious.init({
    formatter: formatter
// Object Example
var formatter = function(annotation) {
    var contributors = [];
    annotation.bodies.forEach(function(body) {
      if (body.creator)
    if (contributors.length > 1) {
      return {
        'data-users': contributors.join(', '),
        'style': 'stroke-width:2; stroke: red'
var anno = Annotorious.init({
    formatter: formatter


v2.3.3 (03/30/2021)

  • Fixed a bug that caused polygons to close in touch mode after ~500ms of idleness, even if the finger wasn’t on the screen (intended behavior is tap-and-hold for ~500ms)
  • Touch mode now works properly on images in scrolled pages
  • Bugfix: when creating a new selection, attempting to modify the shape caused a ‘cancel’. Newly created shapes can now be modified immediately
  • Editor now (finally) auto-positions correctly when moving it outside the browser viewport
  • When allowing empty annotations (allowEmpty: true config option), empty annotations get a delete button

v2.3.2 (03/30/2021)

  • Adds CSS fixes to the style of the tag widget
  • Bugfix: calling .selectAnnotation triggered two selectAnnotation events, when it should trigger any at all – fixed
  • Regression bug fix: resize handles now scale properly again on responsive images
  • Fixed a bug that caused coordinates to shift when annotating images on scrolled-down on touch devices
  • Fixed various minor behavior bugs in touch mode
  • Upgrades some security-patched npm dependencies

v2.3.1 (03/29/2021)

  • Minor behavior tweaks to headless mode.
  • When creating annotations in headless mode that have no bodies, annotations are immediately removed (as they should be), unless the allowEmpty config option is set to true.
  • When changing the drawing tool, the current drawing tool is properly stopped in case drawing is currently ongoing.

v2.3.0 (03/28/2021)

  • Bugfix: .removeAnnotation now allows annotation object or annotation ID as argument
  • Delete Annotation button (finally!), with a mechanism that allows widget plugins to control whether delete is possible or not
  • headless config option now deprecated. Use disableEditor instead
  • disableEditor can be changed without re-initializing Annotorious
  • ReadOnly mode can now be changed without re-initializing Annotorious, through the .readOnly property
  • allowEmpty config option
  • Tweaked touch interaction: both press+hold and move+hold are now translated to double click, which closes the polygon
  • Removed Hammer.js dependency

v2.2.5 (03/17/2021)

  • Switched to Terser for code optimization, due to ongoing security issues with Uglify
  • Fixed errors in the event lifecycle
  • Size-based sorting of polygon shapes, so that large polygon annotations no longer obstruct smaller polygon shapes
  • Internal API changes to enable more powerful plugins
  • Reduced code redundancy in drawing tool implementations
  • .listDrawingTools API method

v2.2.4 (03/11/2021)

  • Fixes a bug that caused .getAnnotations API method to break when called from inside an event handler
  • Adds cancelSelected event when user cancels editing a selection

v2.2.3 (03/10/2021)

  • Fixed cancelSelected event

v2.2.2 (02/28/2021)

  • Fixes a bug that caused wrong editor position when the window is scrolled horizontally
  • Adds support for touch devices

v2.2.1 (02/15/2021)

  • Bugfixes
  • Shape edit handles can now be resized via CSS transform: scale(…)
  • Shape editing now works properly in headless mode
  • Editor: Fixed a minor bug concerning proper display of created/lastModified times; Greek UI language translation
  • Widget API: Widgets now get an updated annotation instance when the user changes the selection target (e.g. move/resize in Annotorious); Added .onSetProperty method that allows widgets to attach top-level props the annotation

v2.2.0 (01/03/2021)

  • Added Dutch UI translation
  • New API method clearAnnotations
  • Added cancelSelection event, when user hits ‘cancel’ on a newly created shape
  • Revised headless API
  • New API method saveSelected to save changes to an annotation programmatically
  • New API method cancelSelected to cancel programmatically
  • Removed support for applyTemplate API function in favor of new headless API. Example: to apply a tag automatically in headless mode

v2.1.7 (12/27/2020)

  • Editor bugfixes
  • Added getSelectedImageSnippet API method

v2.1.6 (12/20/2020)

  • Bugfixes
  • Preparations/compatibility plumbing for editable shapes in OpenSeadragon

v2.1.5 (11/30/2020)

  • Fixes a regression bug that broke shape editing in v2.1.4

v2.1.4 (11/30/2020)

  • UI/behavior: clicking outside the selected shape cancels editing and closes the editor
  • Proper handling of multi-line comments in the Comment Widget
  • Localized text labels for time expressions (“2 minutes ago”), when using authInfo
  • Added missing Spanish labels for ‘Edit’ and ‘Delete’

v2.1.3 (10/14/2020)

  • Dim mask now also available for the polygon drawing tool
  • Czech UI translation
  • Tag widget: fixed broken autosuggest behavior
  • Editor plugins: config params are now properly forwarded to plugin args

v2.1.2 (09/22/2020)

  • Environment is no longer a global object, meaning that it is now safe to use multiple Recogito/Annotorious instances on the same page
  • All CSS classes are now properly prefixed to avoid clashes with other styles on the page (either with a9s for Annotorious-specific elements or r6o for elements imported from Recogito core
  • Small bugfixes to the dim mask

v2.1.1 (09/20/2020)

  • CSS styles are no longer embedded in the JavaScript file, but now have to be imported separately.
  • Editor widgets are becoming more flexible. This release is the first to include beta support for a plugin API. As a consequence, this version introduces a minimal change to how the tag widget is configured with a controlled vocabulary.

v2.0.8 (09/13/2020)

  • Minor bugfix

v2.0.7 (08/29/2020)

  • IE11 support bugfixes

v2.0.6 (08/29/2020)

  • IE11 compatibility
  • Editable polygon shapes
  • Bugfixes concerning the behavior of the tag autosuggest component
  • Security fixes for library dependencies

v2.0.5 (07/12/2020)

  • Added babel polyfill (IE11 compat)

v2.0.4 (07/12/2020)

  • Beta support for rendering any SVG shape contained in W3C Web Annotations
  • Beta support for polygon drawing
  • Various bugfixes
  • Portuguese UI translation
  • Tag widget: controlled vocabulary autosuggest
  • Selecting an annotation now adds a selected CSS class

v2.0.3 (06/12/2020)

  • Various smaller bugfixes
  • Microsoft Edge compatibility
  • Experimental support for responsive images
  • Web Annotation standard compliance: target now includes a source property with the image source URL
  • Minor API changes: selectAnnotation method now returns selected annotation object and does not fire the selectAnnotation event
  • Added support for internationalization
  • Ability to handle user information for UI display and when creating/updating annotations
  • Ability to add created and modified timestamps, with an option for the host application to sync with the server time

v2.0.2 (05/21/2020)

  • Minor bugfixes
  • Enabling readOnly annotations

v2.0.2 (05/21/2020)

  • Minor bugfixes

You Might Be Interested In:

One thought on “Annotating An Image In JavaScript – Annotorious

Leave a Reply