annotorious: Basic react functional component widget doesn't work

Hello, I’m using Annotorious 2.7.1, I was trying to do a minimal example of a React widget but it doesn’t seem to work and I get the error: TypeError: can't define property "__": Object is not extensible I have tried defining the widget like this:

const TestWidget = (props) => <div>Test widget</div>

And like this:

class UnitWidget extends Component {
  render() {
    return <div>Test widget</div>
  }
}

and I’m initializing Anno with:

      annotorious = new Annotorious({
        image,
        widgets: [{widget: TestWidget, force: 'react'}]
      });

I have tried the plainjs example from https://recogito.github.io/guides/editor-widgets/ and that works fine, the problem seems only to be when I try to use the React component functionality. I’m sort of fumbling in the dark/source code since I couldn’t find any docs on using this with react, so I might just be missing something and would appreciate any help

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 83 (46 by maintainers)

Most upvoted comments

@rsimon @TomDijkema I think I’ve faced a similar issue with the popup not really being where it should be, but being consistently offset by a certain amount. In my case, this was in fact the offset of the OSD container.

I’m on v2, but using the code for the v3 popup to be a headless popup in v2. Adding the offset of the viewer to the annotation bounding rect that the popup position is based on solved it for me -

  // Get the viewer bounding rect
  const viewerBounds = viewer.element.getBoundingClientRect();

  // Annotation coordinates -> viewer element coordinates
  // Assuming that the min/max coordinates of your annotation are determined from the annotation's target selector
  const topLeft = viewer.viewport.imageToViewerElementCoordinates(
    new OpenSeadragon.Point(minX, minY)
  );
  const bottomRight = viewer.viewport.imageToViewerElementCoordinates(
    new OpenSeadragon.Point(maxX, maxY)
  );

  // The return here is the adjusted bounding rect of the annotation in the DOM. 
  return {
    x: topLeft.x + viewerBounds.x,
    right: bottomRight.x + viewerBounds.x,
    y: topLeft.y + viewerBounds.y,
    bottom: bottomRight.y + viewerBounds.y,
    width: bottomRight.x - topLeft.x,
    height: bottomRight.y - topLeft.y,
  };

I think I got most of it working, adding, editing and removing annotations. We are still working on the API a bit, but when its done I should also be able to share my solution with you.

Many thanks for the help until now! I hope more people will find this new version of the package useful for implementation within JavaScript frameworks!

Great!

I added W3CImageAnnotation and W3CImageAnnotationTarget as re-exports to the @annotorious/openseadragon and @annotorious/react packages. So installing @annotorious/annotorious won’t be necessary anymore from the next release onwards.

I think there won’t be a way around using as W3CImageAnnotationTarget though. W3CImageAnnotations are allowed to have either a single target, or a list, which is why TS can’t infer. (I guess you could do something like if (Array.isArray(target)) { ... } though.)

Hi,

that’s all great to hear. The release candidates are getting pretty stable now. Incremental enhancements rather than breaking changes! Things are basically ready to go, I’m just hesitant to put a real “v3.0.0” label on them before there is…

  • proper documentation…
  • an add-on package that emulates the built-in popup from v2.7, and provides a simple migration path for those who are using v2 with the popup now

This means I still can’t say exactly when launch day will be. But at least, releases should become pretty stable from now on.

Concerning the TypeScript issues.

  • Hm, the annotation types are in @annotorious/core. Can you check your node_modules folder if the core module is actually there, in the @annotorious folder? If not, you could try deleting node_modules and package-lock, and running a fresh npm install.
  • Good point about the pointerSelectAction. Yes, I think it would make sense to run that through the adapter. I created an issue for this here: #357

Yeah the image server itself is probably the issue and the solution, will have to contact the people behind it. Either way, I still tried the converting option, but indeed that option fails due to the fetch getting the same CORS based error. The proxy suggestion could work, we do have an unforeseeable amount of image servers to include, so we will have to make a strategy for this.

Thanks again for thinking with me!

Ok, thanks. Come to think of it… I could imagine there are several situations where the React <OpenSeadragonAnnotator> gets remounted. Because there’s no .destroy method yet that could get called when unmounting, this might lead to stray annotations. I’ll investigate in any case, and add a destroy() method + proper unmounting for the next package release.

I just published a new Annotorious 3 (pre-)release with all the latest fixes, including @abiswas97’s popup fix (thanks again!) and a fix that may (or may not…) solve your problem with stray annotations, @TomDijkema.

https://www.npmjs.com/package/@annotorious/react/v/3.0.0-pre-alpha-50

@rsimon yup I’m using the OpenSeadragonPopup component, and this was a small modification made to the getAnnotationDomRect function in the setPosition file. Should I open a PR for this?

Nevermind, found the selectionChanged method, which should also work!

Ok, that’s wild. I wasn’t aware - but I can reproduce this on Firefox with my own popup, too. Regardless of where you click, it has the same effect as if clicking outside. It doesn’t seem to happen every time. But most of the time.

I’ll definitely make a note about that on our own issue tracker, and will try to get to the bottom of it. Let me know if you can find any more hints that might point to the root cause.

Excellent! Good to hear it’s working now.

If you have the time, do keep me posted about your progress. I’m really interest in hearing how it goes (and how people are making use of Annotorious!)

Looks all good, too. Ok, I’ll dig into it later. Let’s see if there’s anything I can reproduce.

That’s a first for me 😃.

Ok, used the Tooltip to recreate the old popup window. The option to add your own custom elements in here is very useful and is just the solution we needed for this Github issue. The tooltip placement is a bit wacky at some times, liked that the version 2 one always was displayed at a fixed position below the annotation.

The pointerSelectAction method works for edit, but highlight does not show anything for me. Also by default all annotations are invisible, only becoming visible when I click on them with the edit method. My expectation would be that all annotations are visible using grey-ish borders like in version 2 and become yellow when highlighted. At first I thought this might have to do with a styling issue, but now I think it has to do with the annotations not being present in the DOM when not selected with edit mode. The <g> element does exist on the annotation layer, but it is not populated until you trigger the edit mode for an annotation. Is this on purpose?

Ah yes! You are correct, I was missing the top Annotorious component that wraps it all up. Now the viewer works just like normal. Will continue trying to apply the annotation methods now.

Regarding sourcemaps, I am afraid I do not have any experience with them, seems like it has to do with the build configuration like you said, so that it generates more specific error logs.

Hi @TomDijkema,

yes, the new version supports OpenSeadragon. Likewise: there is still only minimal documentation. But if you are willing to give it a try - here’s pretty much the absolute minimal setup for using Annotorious 3, OpenSeadragon version, via React bindings:

https://github.com/annotorious/annotorious-v3/blob/main/packages/annotorious-react/test/App.tsx

In principle, everything is contained in the @annotorious/react package, which you can install from the npm registry.

I’m currently using this package heavily myself in one of my own projects. The codebase for this is a little big as an “introductory example”… But if you want to dig in: it would definitely give you more hints from a real-world scenario.

https://github.com/recogito/recogito-client/blob/main/src/apps/annotation-image/ImageAnnotationDesktop.tsx