mirror of
https://github.com/hakimel/reveal.js.git
synced 2025-08-02 12:48:13 +02:00
reader mode remembers scroll position when reloading
This commit is contained in:
2
dist/reveal.esm.js
vendored
2
dist/reveal.esm.js
vendored
File diff suppressed because one or more lines are too long
2
dist/reveal.esm.js.map
vendored
2
dist/reveal.esm.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/reveal.js
vendored
2
dist/reveal.js
vendored
File diff suppressed because one or more lines are too long
2
dist/reveal.js.map
vendored
2
dist/reveal.js.map
vendored
File diff suppressed because one or more lines are too long
@@ -42,7 +42,6 @@ export default class Reader {
|
|||||||
const horizontalSlides = queryAll( this.Reveal.getRevealElement(), HORIZONTAL_SLIDES_SELECTOR );
|
const horizontalSlides = queryAll( this.Reveal.getRevealElement(), HORIZONTAL_SLIDES_SELECTOR );
|
||||||
|
|
||||||
this.viewportElement.classList.add( 'loading-scroll-mode', 'reveal-reader' );
|
this.viewportElement.classList.add( 'loading-scroll-mode', 'reveal-reader' );
|
||||||
this.viewportElement.addEventListener( 'scroll', this.onScroll, { passive: true } );
|
|
||||||
|
|
||||||
let presentationBackground;
|
let presentationBackground;
|
||||||
|
|
||||||
@@ -134,11 +133,14 @@ export default class Reader {
|
|||||||
this.Reveal.layout();
|
this.Reveal.layout();
|
||||||
this.Reveal.setState( stateBeforeActivation );
|
this.Reveal.setState( stateBeforeActivation );
|
||||||
|
|
||||||
this.viewportElement.classList.remove( 'loading-scroll-mode' );
|
|
||||||
|
|
||||||
this.activatedCallbacks.forEach( callback => callback() );
|
this.activatedCallbacks.forEach( callback => callback() );
|
||||||
this.activatedCallbacks = [];
|
this.activatedCallbacks = [];
|
||||||
|
|
||||||
|
this.restoreScrollPosition();
|
||||||
|
|
||||||
|
this.viewportElement.classList.remove( 'loading-scroll-mode' );
|
||||||
|
this.viewportElement.addEventListener( 'scroll', this.onScroll, { passive: true } );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -253,7 +255,7 @@ export default class Reader {
|
|||||||
|
|
||||||
if( this.isActive() ) {
|
if( this.isActive() ) {
|
||||||
this.syncPages();
|
this.syncPages();
|
||||||
this.onScroll();
|
this.syncScrollPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -587,6 +589,67 @@ export default class Reader {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the current scroll position and updates our active
|
||||||
|
* trigger states accordingly.
|
||||||
|
*/
|
||||||
|
syncScrollPosition() {
|
||||||
|
|
||||||
|
const viewportHeight = this.viewportElement.offsetHeight;
|
||||||
|
const viewportHeightFactor = viewportHeight / this.viewportElement.scrollHeight;
|
||||||
|
|
||||||
|
const scrollTop = this.viewportElement.scrollTop;
|
||||||
|
const scrollHeight = this.viewportElement.scrollHeight - viewportHeight
|
||||||
|
const scrollProgress = Math.max( Math.min( scrollTop / scrollHeight, 1 ), 0 );
|
||||||
|
const scrollProgressMid = Math.max( Math.min( ( scrollTop + viewportHeight / 2 ) / this.viewportElement.scrollHeight, 1 ), 0 );
|
||||||
|
|
||||||
|
let activePage;
|
||||||
|
|
||||||
|
this.slideTriggers.forEach( ( trigger ) => {
|
||||||
|
const { page } = trigger;
|
||||||
|
|
||||||
|
const shouldPreload = scrollProgress >= trigger.range[0] - viewportHeightFactor*2 &&
|
||||||
|
scrollProgress <= trigger.range[1] + viewportHeightFactor*2;
|
||||||
|
|
||||||
|
// Load slides that are within the preload range
|
||||||
|
if( shouldPreload && !page.loaded ) {
|
||||||
|
page.loaded = true;
|
||||||
|
this.Reveal.slideContent.load( page.slideElement );
|
||||||
|
}
|
||||||
|
else if( page.loaded ) {
|
||||||
|
page.loaded = false;
|
||||||
|
this.Reveal.slideContent.unload( page.slideElement );
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're within this trigger range, activate it
|
||||||
|
if( scrollProgress >= trigger.range[0] && scrollProgress <= trigger.range[1] ) {
|
||||||
|
this.activateTrigger( trigger );
|
||||||
|
activePage = trigger.page;
|
||||||
|
}
|
||||||
|
// .. otherwise deactivate
|
||||||
|
else if( trigger.active ) {
|
||||||
|
this.deactivateTrigger( trigger );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
// Each page can have its own scroll triggers, check if any of those
|
||||||
|
// need to be activated/deactivated
|
||||||
|
if( activePage ) {
|
||||||
|
activePage.scrollTriggers.forEach( ( trigger ) => {
|
||||||
|
if( scrollProgressMid >= trigger.range[0] && scrollProgressMid <= trigger.range[1] ) {
|
||||||
|
this.activateTrigger( trigger );
|
||||||
|
}
|
||||||
|
else if( trigger.active ) {
|
||||||
|
this.deactivateTrigger( trigger );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update our visual progress indication
|
||||||
|
this.setProgressBarValue( scrollTop / ( this.viewportElement.scrollHeight - viewportHeight ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves the progress bar playhead to the specified position.
|
* Moves the progress bar playhead to the specified position.
|
||||||
*
|
*
|
||||||
@@ -657,6 +720,37 @@ export default class Reader {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persists the current scroll position to session storage
|
||||||
|
* so that it can be restored.
|
||||||
|
*/
|
||||||
|
storeScrollPosition() {
|
||||||
|
|
||||||
|
clearTimeout( this.storeScrollPositionTimeout );
|
||||||
|
|
||||||
|
this.storeScrollPositionTimeout = setTimeout( () => {
|
||||||
|
sessionStorage.setItem( 'reveal-reader-scroll', this.viewportElement.scrollTop );
|
||||||
|
sessionStorage.setItem( 'reveal-reader-scroll-origin', location.origin + location.pathname );
|
||||||
|
|
||||||
|
this.storeScrollPositionTimeout = null;
|
||||||
|
}, 50 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restores the scroll position when a deck is reloader.
|
||||||
|
*/
|
||||||
|
restoreScrollPosition() {
|
||||||
|
|
||||||
|
const scrollPosition = sessionStorage.getItem( 'reveal-reader-scroll' );
|
||||||
|
const scrollOrigin = sessionStorage.getItem( 'reveal-reader-scroll-origin' );
|
||||||
|
|
||||||
|
if( scrollPosition && scrollOrigin === location.origin + location.pathname ) {
|
||||||
|
this.viewportElement.scrollTop = parseInt( scrollPosition, 10 );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activates the given page and starts its embedded conten
|
* Activates the given page and starts its embedded conten
|
||||||
* if there is any.
|
* if there is any.
|
||||||
@@ -775,58 +869,8 @@ export default class Reader {
|
|||||||
|
|
||||||
onScroll() {
|
onScroll() {
|
||||||
|
|
||||||
const viewportHeight = this.viewportElement.offsetHeight;
|
this.syncScrollPosition();
|
||||||
const viewportHeightFactor = viewportHeight / this.viewportElement.scrollHeight;
|
this.storeScrollPosition();
|
||||||
|
|
||||||
const scrollTop = this.viewportElement.scrollTop;
|
|
||||||
const scrollHeight = this.viewportElement.scrollHeight - viewportHeight
|
|
||||||
const scrollProgress = Math.max( Math.min( scrollTop / scrollHeight, 1 ), 0 );
|
|
||||||
const scrollProgressMid = Math.max( Math.min( ( scrollTop + viewportHeight / 2 ) / this.viewportElement.scrollHeight, 1 ), 0 );
|
|
||||||
|
|
||||||
let activePage;
|
|
||||||
|
|
||||||
this.slideTriggers.forEach( ( trigger ) => {
|
|
||||||
const { page } = trigger;
|
|
||||||
|
|
||||||
const shouldPreload = scrollProgress >= trigger.range[0] - viewportHeightFactor*2 &&
|
|
||||||
scrollProgress <= trigger.range[1] + viewportHeightFactor*2;
|
|
||||||
|
|
||||||
// Load slides that are within the preload range
|
|
||||||
if( shouldPreload && !page.loaded ) {
|
|
||||||
page.loaded = true;
|
|
||||||
this.Reveal.slideContent.load( page.slideElement );
|
|
||||||
}
|
|
||||||
else if( page.loaded ) {
|
|
||||||
page.loaded = false;
|
|
||||||
this.Reveal.slideContent.unload( page.slideElement );
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're within this trigger range, activate it
|
|
||||||
if( scrollProgress >= trigger.range[0] && scrollProgress <= trigger.range[1] ) {
|
|
||||||
this.activateTrigger( trigger );
|
|
||||||
activePage = trigger.page;
|
|
||||||
}
|
|
||||||
// .. otherwise deactivate
|
|
||||||
else if( trigger.active ) {
|
|
||||||
this.deactivateTrigger( trigger );
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
// Each page can have its own scroll triggers, check if any of those
|
|
||||||
// need to be activated/deactivated
|
|
||||||
if( activePage ) {
|
|
||||||
activePage.scrollTriggers.forEach( ( trigger ) => {
|
|
||||||
if( scrollProgressMid >= trigger.range[0] && scrollProgressMid <= trigger.range[1] ) {
|
|
||||||
this.activateTrigger( trigger );
|
|
||||||
}
|
|
||||||
else if( trigger.active ) {
|
|
||||||
this.deactivateTrigger( trigger );
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update our visual progress indication
|
|
||||||
this.setProgressBarValue( scrollTop / ( this.viewportElement.scrollHeight - viewportHeight ) );
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user