daybrush / infinite-viewer

Infinite Viewer is Document Viewer Component with infinite scrolling.
https://daybrush.com/infinite-viewer/
MIT License
296 stars 33 forks source link

Question: can we animate programatic change of zoom/position? #34

Open bytasv opened 2 years ago

bytasv commented 2 years ago

Hey there,

I was wondering if it is possible to animate somehow the transition between whatever zoom and canvas position we currently have new values that I'd like to set?

I.e.: I want to reset the zoom to 100% and center canvas on some keyboard press, right now it immediately jumps to that setting, but I thought it would be nice to see even the quick transition in between. I could probably try to animate it with setTimout/raf but don't think it's gonna be a good result and maybe it wouldn't be too difficult to add some line in the code to have this functionality. 🤔

daybrush commented 2 years ago

@bytasv

The viewer.setZoom method The viewer.scrollTo method and the viewer.scrollBy method exist.

bytasv commented 2 years ago

I'm using these methods to set viewer position/zoom, however they just do it instantly, I was wondering if it would be possible to add an option to enable transition/animation to the new state?

daybrush commented 2 years ago

@bytasv

Would it be ok to provide it as scrollTo(0, 0, duration), setZoom(1, duration)? Instead, it can be difficult to determine the easing.

bytasv commented 2 years ago

I think duration makes sense, I'd just pass options object like { duration } instead of adding more args to those methods. I'm not sure how are you thinking to implement it, but if you were to use CSS animations or same timing functions as CSS provides, maybe the full API could look like this:

interface Options {
    animate?: boolean,
    duration?: number // some sane default? 
    timingFunction?: string // ease as default
}
//...
scrollTo(x, y, options: Options)

And then obviously if you decide to add more arguments, you can just use same options argument 🤔

daybrush commented 2 years ago

@bytasv

I'll develop this week (or until next week)

daybrush commented 2 years ago

@bytasv

infinite-viewer's new version is released. setZoom, scrollTo, scrollBy have animation options added.

.setZoom(1.2, {
   easing: (x: number) => number,
   duration: 200,
});
.scrollTo(0, 0, {
   easing: (x: number) => number,
   duration: 200,
});
.scrollBy(0, 0, {
   easing: (x: number) => number,
   duration: 200,
});
bytasv commented 2 years ago

Thanks a lot! I just tested it out, seems to be working, but now I realised that I might have an issue if I want to both re-center and reset zoom at the same time, i.e.:

viewerRef.current.setZoom(zoomValue, { duration: 5000 })
viewerRef.current.scrollCenter({ duration: 5000 })

This produces this really weird effect

https://user-images.githubusercontent.com/437214/193652900-025e75e4-de27-4b59-a1ac-a1467335936b.mov

I don't see a method that I could use to both zoom and scroll at the same time, am I missing something or it's not there? Wondering if it would be possible to add that? Or maybe extend scrollCenter so that it would also accept zoom level? 🤔

daybrush commented 1 year ago

@bytasv This is a phenomenon that occurs because the amount of scrolling moved through setZoom is greater than scrollCenter.

infinite-viewer's new version is released.

absolute property is added in ScrollOptions (default: false) zoomBase property is added in ZoomOptions (default "screen")

viewer.scrollCenter({ duration: 5000, absolute: true }); viewer.setZoom(1.2, { duration: 5000, zoomBase: "viewport" });