Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

show and hide svg overlay #49

Open
gmhud opened this issue Aug 9, 2024 · 10 comments
Open

show and hide svg overlay #49

gmhud opened this issue Aug 9, 2024 · 10 comments
Labels

Comments

@gmhud
Copy link

gmhud commented Aug 9, 2024

Is it possible to show and hide overlays as a whole? (created through var overlay = viewer.svgOverlay() ? )

I tried viewer.world.getItemAt(x).setOpacity and many other options without success.

Also, is it possible to create hover / mouseover events for svg elements in the overlay?

Thanks

@iangilman
Copy link
Member

You should be able to work with the SVG elements attached to the overlay just like you would work with any SVG. If you want to be able to hide & show the entire thing, you could attach a g node at the top level and then hide and show it as needed.

I'm not sure about hovers. Have you tried attaching normal event handlers to your SVG objects? Click should work at least, but I haven't tried mouseover.

In https://iangilman.com/openseadragon/flickr/ the text is done with the SVG overlay. You can see they accept clicks, but I didn't give them hovers.

@msalsbery
Copy link
Member

msalsbery commented Aug 9, 2024

pointerenter/pointerleave and/or pointerover/pointerout event handlers should work well for hover. SVG hit testing is amazingly good in my experience 😅

@gmhud
Copy link
Author

gmhud commented Aug 10, 2024

In the end I did the show and hide by iterating through each of the elements of a class assigned to the svgs (I wanted to show and hide different groups of elements).

I couldn't see how to create multiple svg-overlays and assign them different Ids, in order to change the visibility for the whole layer at once via the Id. I concluded there can only be one svg-overlay per openseadragon instance, so you can't create a separate overlay for different groups of svgs?

Mouseover works fine, but it is difficult to work out what reference system to use for mousepointer coordinates for associated popups etc.

To create elements (with d3):

var overlay = viewer.svgOverlay();

var d3Circle = d3.select(overlay.node())
.append("circle")
.attr("cx", 0.5)
.attr("cy", 0.5)
.attr("r", 0.05)
...
.attr("class", "circles")
.style("visibility", "hidden")
.on("mouseover", function(){return someFunctionOrOther});

var d3Circle = d3.select(overlay.node())
.append("circle")
.attr("cx", 0.5)
.attr("cy", 0.5)
.attr("r", 0.05)
...
.attr("class", "circles")
.style("visibility", "hidden")
.on("mouseover", function(){return someOtherFunctionOrOther});

To toggle visibility:

var a = document.getElementsByClassName('circles')
for (var i = 0; i < a.length; i++) {
if (a[i].style.visibility == "hidden") {a[i].style.visibility="visible"} else {a[i].style.visibility="hidden"}
}

@iangilman
Copy link
Member

Glad you found something that worked!

Yes, just one SVG overlay per viewer. You can add as many SVG groups as you want, though, so you can easily have different groups you turn on and off if you want.

I believe the coordinates in the SVG overlay match the viewport coordinates of the OSD viewer. There are lots of conversion functions in OSD for the different coordinate systems. If you're not familiar with viewport coordinates, here's a good starting point: https://openseadragon.github.io/examples/viewport-coordinates/

@gmhud
Copy link
Author

gmhud commented Aug 12, 2024

How do I get the mouse click x,y postion though in the first place to pass to the svg element onClick event ?

overlay.onClick(document.getElementsByClassName('Circles')[0], function() {viewer.viewport.zoomTo(8,(new OpenSeadragon.Point(get-x-somehow, get-y-somehow)),false)});

thanks

@iangilman
Copy link
Member

I assume the click will be in web coordinates, so you can do something like this:

overlay.onClick(document.getElementsByClassName('Circles')[0], function(event) {
    const viewportPos = viewer.viewport.windowToViewportCoordinates(event.clientX, event.clientY);
    viewer.viewport.zoomTo(8, viewportPos, false);
});

@gmhud
Copy link
Author

gmhud commented Aug 13, 2024

With this I get an error, as event.clientX and event.clientY are undefined.

@gmhud
Copy link
Author

gmhud commented Aug 14, 2024

overlay.onClick(document.getElementsByClassName('Circles')[0], function() {
viewer.viewport.zoomTo(8,(new OpenSeadragon.Point(event.clientX, event.clientY),false)); console.log(viewer.viewport.windowToViewportCoordinates(event.clientX, event.clientY))});

This now works for the clientX and Y coordinates, but the function in the console log to convert to viewport coordinates returns an error: "Uncaught TypeError: e.minus is not a function".

What would the correct conversion be? thanks

@gmhud
Copy link
Author

gmhud commented Aug 14, 2024

OK, got it:

overlay.onClick(document.getElementsByClassName('PurpleLake')[i], function() {
viewportPosition = viewer.viewport.windowToViewportCoordinates(new OpenSeadragon.Point(event.clientX, event.clientY));
viewer.viewport.zoomTo(8,(viewportPosition),false)
});

windowToViewportCoordinates takes a point not coordinates, I guess.

@iangilman
Copy link
Member

Oh, right! Sorry about that. Glad you got it sorted out :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants