openseadragon / openseadragon

An open-source, web-based viewer for zoomable images, implemented in pure JavaScript.
http://openseadragon.github.io/
BSD 3-Clause "New" or "Revised" License
3k stars 594 forks source link

How to create scroll in OpenSeaDragon canvas #1432

Open NiteshSaxena opened 6 years ago

NiteshSaxena commented 6 years ago

Hello, We are using DeepZoomImages in OpenSeaDragon. OpenSeaDragon by default enables the drag of image on the canvas. We want to prevent drag of the images and give a scroll instead. I have tried using CSS to giving height and setting overflow but that does not work when zooming into the image. Am I missing something? Help would be greatly appreciated.

iangilman commented 6 years ago

OSD does not directly support using the scroll wheel gesture to pan the scene.

Unfortunately replicating the scroll that's built into the browser is actually quite challenging; you can kind of approximate it, but the feel isn't quite the same. At any rate, you can certainly capture scroll wheel events and translate them to pan if you want.

Another approach I've had some success with is creating a clear scrolling element on top of the viewer, and using its scroll value to update the pan of the viewer. Since all of your mouse events will go into that element, you'll have to translate whatever other clicks, etc you want to get through. You can see this approach here:

http://iangilman.com/osd/test/demo/m2/

Here's the code:

https://github.com/openseadragon/openseadragon/blob/master/test/demo/m2/js/main.js

I don't see us including this functionality directly in OSD, but it could be an interesting plugin if someone wanted to make it.

yadielar commented 2 years ago

Hi @iangilman, I know this is an old issue but I was attempting some of the suggestions you mention here and I had a question that hopefully doesn't take you too much of your valuable time to answer.

It's regarding these comments above:

Since all of your mouse events will go into that element, you'll have to translate whatever other clicks, etc you want to get through.

In the demo you shared I see that you're handling click and mousemove events happening in the scrollable element. But you're mostly doing some custom behavior in those handlers, not necessarily forwarding the events as-is to the viewer.

Do you by any chance have an example of how to capture most gesture events (clicks, drags, hovers, etc.) from the scrolling element and simply forward them to the viewer.

I'm mostly interested in just adding support for panning by scroll, and will only disable the scrollToZoom feature. Everything else from OpenSeadragon I would like to work the same.

Any code snippet you can share will be very helpful! 🙂

iangilman commented 2 years ago

@yadielar have you tried/considered the other approach I suggested, where you translate wheel events into panning? It won't as accurately reflect what normal browser scrolling would look like, but it avoids a lot of other tricky issues (like how to manage the hover states for buttons). It would go something like this:

var scrollFactor = 10; // Or whatever's nice

viewer.addHandler('canvas-scroll', function(event) {
  var scrollY = viewer.viewport.deltaPointsFromPixels(event.scroll * scrollFactor);
  viewer.viewport.panBy(new OpenSeadragon.Point(0, scrollY));
});

I haven't tested that code, but it should be the basic idea. Worth a try at least!

yadielar commented 2 years ago

@iangilman yes, and I had something similar to your snippet but using the delta values from the wheel event. But I was wondering if the other approach might feel more natural. I suppose I will go with the first approach then.

And thanks for sharing that code! I was doing something much more complicated with the canvas' actual wheel events, don't know how I missed that canvas-scroll event in the docs!

One thing I'm not sure how to do is constraining the scroll to the bounds of the image. Is the applyConstraints function in your demo code above a good starting point to do that?

iangilman commented 2 years ago

Cool. I mean, if you want to pursue the more involved approach (where you have a scrolling div and you translate it into panning), I can certainly try to point you in the right direction; just be aware that it is likely a lot more work to get the details right!

As for constraining the scroll, sure, that applyConstraints function is probably a good start. It's probably more complicated than what you need, but at least it can give you some ideas. I think the basic idea is pretty straightforward: figure out what the viewport bounds will look like after panning, and if they would be past the content bounds, shift them back.