fix: make the reading viewport a script-driven scroll container so sticky and view timelines work
This commit is contained in:
@@ -48,8 +48,10 @@ export function createSignStage(resources: SceneResourceBag) {
|
||||
Math.min(window.scrollY, contentHeight - viewportHeight),
|
||||
);
|
||||
if (offset !== lastOffset) {
|
||||
main.style.transform = `translate3d(0, ${-offset}px, 0)`;
|
||||
// The viewport is a real (overflow: hidden) scroll container driven by
|
||||
// the document scroll, so sticky and view-timeline layout work inside it.
|
||||
lastOffset = offset;
|
||||
viewport.scrollTop = offset;
|
||||
}
|
||||
// Quantize the opening reveal: the mask image is rebuilt at most
|
||||
// REVEAL_STEPS times on the way in instead of on every scroll event.
|
||||
@@ -149,6 +151,21 @@ export function createSignStage(resources: SceneResourceBag) {
|
||||
};
|
||||
|
||||
resources.listen(window, 'scroll', moveContent, { passive: true });
|
||||
// Anything the browser scrolls inside the viewport (find-in-page, focus,
|
||||
// scrollIntoView) is forwarded to the document, which stays the one scroller.
|
||||
if (viewport)
|
||||
resources.listen(
|
||||
viewport,
|
||||
'scroll',
|
||||
() => {
|
||||
if (!ownsStage() || Number.isNaN(lastOffset)) return;
|
||||
const drift = viewport.scrollTop - lastOffset;
|
||||
if (Math.abs(drift) < 1) return;
|
||||
viewport.scrollTop = lastOffset;
|
||||
window.scrollBy({ top: drift, behavior: 'instant' });
|
||||
},
|
||||
{ passive: true },
|
||||
);
|
||||
const layoutChanged = () => {
|
||||
dirty = true;
|
||||
if (ownsStage()) update(root.clientWidth, window.innerHeight);
|
||||
@@ -184,7 +201,7 @@ export function createSignStage(resources: SceneResourceBag) {
|
||||
delete stage.dataset.readingStage;
|
||||
stage.style.removeProperty('height');
|
||||
}
|
||||
main.style.removeProperty('transform');
|
||||
if (viewport) viewport.scrollTop = 0;
|
||||
viewport?.style.removeProperty('mask-image');
|
||||
viewport?.style.removeProperty('height');
|
||||
for (const image of lazyImages) image.loading = 'lazy';
|
||||
|
||||
Reference in New Issue
Block a user