openseadragon / svg-overlay

An OpenSeadragon plugin that adds SVG overlay capability.
BSD 3-Clause "New" or "Revised" License
58 stars 28 forks source link

Flip .svg functionality #45

Closed CodingMoore closed 2 years ago

CodingMoore commented 2 years ago

Hi Ian,

Thank you (and everyone else) for helping on the discord channel.

I am using the svg-overlay plugin for OSD to lay a set of complicated and nested svg elements over the top of images in a high accuracy application. Unfortunately, while the flip function works great on the tiled image, it does not affect the svg on top. As a side affect, the svg's x-coordinates are reversed, so when I drag the image right, the svg moves left. This is a pretty nifty parallax affect, but definitely isn't what I'm going for.

I would love for the svg to flip with the image, keeping it's exact positioning -- as if the svg were part of the image. My viewer and overlay code are below for reference.

    var viewer = OpenSeadragon({
        id: "openSeaDragonWrapper",
        prefixUrl: "../openseadragon/images/",
        defaultZoomLevel: 0,
        preload: true,
        immediateRender: true,
        homeButton: "plateResetPanZoomButton",
        flipButton: "plateFlipButton",
        showFlipControl: true,
        showRotationControl: true,
        showNavigator: true,
        maxZoomPixelRatio: 4,
        zoomPerScroll: 2,
        tileSources: [
        {
          width: 4000,
          tileSource: {
            //required
            type: "zoomifytileservice",
            width: 2048,
            height: 2048,
            tilesUrl:
              "../assets/ZoomifyImageExample/",
            //optional
            tileSize: 256,
            fileFormat: "jpg"
          },
        },
      ],
    });

    var overlay = viewer.svgOverlay()
    //overlay.node().parentNode.style.pointerEvents = 'none';
    overlay.node().append(svgImage)

    for (let i=0; i < overlay._node.childNodes[0].childNodes.length -1; i++) {
      if(overlay._node.childNodes[0].childNodes[i].nodeName === "a"){
        new OpenSeadragon.MouseTracker({  
          element: overlay._node.childNodes[0].childNodes[i],
          clickHandler: function(event) {
            var target = event.originalEvent.target;
            if (target.matches('a')) {
              if (target.getAttribute('target') === '_blank') {
                window.open(target.getAttribute('href'));
              } else {
                location.href = target.getAttribute('href');
              }
            }
          }
        });
      }
    }
iangilman commented 2 years ago

Yes, this is a great idea! This plugin supports rotation, but not flipping yet. Adding flip support shouldn't be too hard; I would recommend looking at the existing rotation support as a guide. You would want to watch for flip events similar to this:

https://github.com/openseadragon/svg-overlay/blob/edb9d4b64a885abf2609f048da97354307fdfd45/openseadragon-svg-overlay.js#L53

... And actually calculate the effects of the flip here:

https://github.com/openseadragon/svg-overlay/blob/edb9d4b64a885abf2609f048da97354307fdfd45/openseadragon-svg-overlay.js#L87

I imagine it's a matter of negating one dimension of the scale. At the moment the scale is just a single number, but you can also use two numbers with a comma between them in the transform.

If you want to take this on, let me know if you have questions! Otherwise, perhaps someone else will take an interest.

CodingMoore commented 2 years ago

Thanks for weighing in Ian! I will be making an attempt, but in this case I would be more than happy if anyone else wanted to make this happen sooner. I'm trying to get this operational for an art installation that opened last week.

I'm sure I will have questions :)

CodingMoore commented 2 years ago

A pull request has been made here: https://github.com/openseadragon/svg-overlay/pull/46

The proposed code links the state of the svg flip to that of the tiled image.