kit icon indicating copy to clipboard operation
kit copied to clipboard

get access to scroll positions in navigation callbacks

Open kinglouie opened this issue 2 years ago • 10 comments

Describe the problem

I am developing an animation heavy website with sveltekit where i have a three.js scene in a layout that does some transitioning between pages and also on scroll. The issue I am facing is that when using browser back button and the previous page was scrolled down, i can not do the correct page transition animation because I don't know the scroll offset of the target page. At the moment I transition the three.js scene as if the target page is at 0 y offset and then the scene updates according to the scroll position with a visible disruption.

Repro:

  1. visit https://www.morrowsix.de/
  2. scroll down a bit and click on one of the two project cards
  3. use browser back button

Result: logo in the background scene transitions as if target page was at 0 y offset and then the scenes update function that uses the scroll offset puts the logo in the correct position.

Currently i trigger my transition animation in beforeNavigate

Describe the proposed solution

have the target page scroll offset available somewhere in beforeNavigate and/or afterNavigate

Alternatives considered

I digged a bit in the source and found that sveltekit saves the scrolloffsets in sessionstorage along with an id that can be matched with the history. Before writing a function to extract the information by myself i wanted to ask here if my proposed solution would be feasable to implement upstream.

Importance

nice to have

Additional Information

No response

kinglouie avatar May 12 '23 06:05 kinglouie

Okay, first of all, cool site!

I don't want to distract from the proposal you're offering, but would adding data-sveltekit-noscroll to your a tags fix this?

If not, could you use <svelte:window bind:scrollY>?

Thanks @tcc-sejohnson :) I do want to keep the behaviour, that the scroll offset is saved in the history. The issue with your other suggestion binding scrollY to a var is, that I only get the current scroll offset but I want to know the scroll offset in advance in beforeNavigate of the page that svelte is navigating to by hitting the browser back button. When beforeNavigate fires, the scrollY value is from the current page not the target page.

kinglouie avatar May 12 '23 20:05 kinglouie

Ohhhh wait, hold on, this sounds like snapshots. Have you seen them?

I'm betting you could:

  • bind to window scrollY
  • Capture scrollY with the capture: () => scrollY
  • Restore it with restore: (scrollY) => /* pass it to Three.js however you need to */

I saw the snapshot feature but I dont think it is a good fit because I believe it is intended to restore state in a component that was unmounted before. In my case the transition animation is happening in the layout which is never unmounted. The thing is, the scrollY position of the previous page is already saved in sessionstorage in the same way snapshots save data. I'm asking for an easy interface to surface this data in beforeNavigate.

I can read the scrollOffsets from all history entries with this:

const scrollOffsets = JSON.parse(window.sessionStorage['sveltekit:scroll'])

this will contain something like this:

1683901763029: Object { x: 0, y: 0 }
1683901763030: Object { x: 0, y: 610 }
1683901763031: Object { x: 0, y: 0 }

but I dont know how to reliably obtain the correct index of the target page in beforeNavigate

kinglouie avatar May 12 '23 20:05 kinglouie

I actually got curious about how to implement this and I don't really think it's that difficult! Check it out:

https://www.sveltelab.dev/ul3q3yf78zk609g

Just a dozen lines in +layout.svelte and you're set.

I would not recommend parsing sveltekit:scroll as it's not a public API and might just up and break on you in the future.

I really appreciate you effort but I think this is kinda reinventing the wheel because the info I need is already in the session storage, this is why I would rather have a interface provided by sveltekit.
I think there might be a few edge cases, for example in your solution it isnt possible to have the same page twice in history with different scroll offsets. Sveltekit already mangages this perfectly but has no interface to this data.

kinglouie avatar May 12 '23 22:05 kinglouie

I understand there may be an edge-case or two -- I'm just trying to get you a solution that will work for now, as it's going to take more time than you probably want to wait to get this feature both approved and implemented (unless Rich swoops in with a magic solution). Most of the team is focused on the Svelte 4 release right now and the rest of us are just volunteers.😉

(I'm not writing off your feature request -- I think it's potentially a good idea! I just want to unblock you for now. I think this gets you close enough not to be stuck waiting on us. ❤️)

I did not want to come across that I brush of your suggested solution. ❤️ The original issue is not really critial or timepressing for me it is just something that I noticed during development, so I wanted to add a feature request here to see if the maintainers would consider adding an interface for this in the future :)

kinglouie avatar May 15 '23 07:05 kinglouie

API proposal:

Extend NavigationTarget with scrollX and scrollY properties.

During a navigation, to would have its scrollX and scrollY parameters set to whatever scroll position Kit intends to restore upon successful navigation. from would have its scrollX and scrollY parameters set to whatever they were at the time of navigation (i.e. whatever number Kit will have / would have stored in sessionStorage for this page).

Now that I'm playing around with the code I'm not sure exactly how all of this would work 🤣 We'll get there!