1
0
mirror of https://github.com/hakimel/reveal.js.git synced 2025-08-11 09:04:51 +02:00

finishing touches on reader mode progress bar

This commit is contained in:
Hakim El Hattab
2023-10-10 13:34:33 +02:00
parent 234799114a
commit a6abd0423e
8 changed files with 130 additions and 58 deletions

View File

@@ -2011,6 +2011,13 @@ $notesWidthPercent: 25%;
position: sticky; position: sticky;
top: 50%; top: 50%;
z-index: 20; z-index: 20;
opacity: 0;
transition: all 0.3s ease;
&.visible,
&:hover {
opacity: 1;
}
.reader-progress-inner { .reader-progress-inner {
position: absolute; position: absolute;
@@ -2021,6 +2028,18 @@ $notesWidthPercent: 25%;
transform: translateY(-50%); transform: translateY(-50%);
border-radius: 8px; border-radius: 8px;
z-index: 10; z-index: 10;
// Hit area
&:after {
content: '';
position: absolute;
width: 200%;
height: 100%;
top: 0;
left: -50%;
background: rgba( 0, 0, 0, 0 );
z-index: -1;
}
} }
.reader-progress-playhead { .reader-progress-playhead {

2
dist/reveal.css vendored

File diff suppressed because one or more lines are too long

2
dist/reveal.esm.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/reveal.js vendored

File diff suppressed because one or more lines are too long

2
dist/reveal.js.map vendored

File diff suppressed because one or more lines are too long

View File

@@ -276,9 +276,15 @@ export default {
// Only applies to presentations in reader mode. // Only applies to presentations in reader mode.
readerScrollSnap: 'proximity', readerScrollSnap: 'proximity',
// Enables and configure the reader mode scroll bar.
// - 'auto': Show the scrollbar while scrolling, hide while idle
// - true: Always show the scrollbar
// - false: Never show the scrollbar
readerScrollBar: 'auto',
// Responsively activate the reader mode when we reach the specified // Responsively activate the reader mode when we reach the specified
// width (in pixels) // width (in pixels)
readerActivationWidth: 800, readerActivationWidth: null,
// The maximum number of pages a single slide can expand onto when printing // The maximum number of pages a single slide can expand onto when printing
// to PDF, unlimited by default // to PDF, unlimited by default

View File

@@ -1,6 +1,8 @@
import { HORIZONTAL_SLIDES_SELECTOR, SLIDES_SELECTOR } from '../utils/constants.js' import { HORIZONTAL_SLIDES_SELECTOR, SLIDES_SELECTOR } from '../utils/constants.js'
import { queryAll, createStyleSheet } from '../utils/util.js' import { queryAll, createStyleSheet } from '../utils/util.js'
const HIDE_SCROLLBAR_TIMEOUT = 500;
/** /**
* The reader mode lets you read a reveal.js presentation * The reader mode lets you read a reveal.js presentation
* as a linear scrollable page. * as a linear scrollable page.
@@ -116,52 +118,6 @@ export default class Reader {
} }
createProgressBar() {
this.progressBar = document.createElement( 'div' );
this.progressBar.className = 'reader-progress';
this.progressBarInner = document.createElement( 'div' );
this.progressBarInner.className = 'reader-progress-inner';
this.progressBar.appendChild( this.progressBarInner );
this.progressBarPlayhead = document.createElement( 'div' );
this.progressBarPlayhead.className = 'reader-progress-playhead';
this.progressBarInner.appendChild( this.progressBarPlayhead );
this.viewportElement.insertBefore( this.progressBar, this.viewportElement.firstChild );
const handleMouseDown = ( event ) => {
event.preventDefault();
document.addEventListener( 'mousemove', handleDocumentMouseMove );
document.addEventListener( 'mouseup', handleDocumentMouseUp );
handleDocumentMouseMove( event );
};
const handleDocumentMouseMove = ( event ) => {
let progress = Math.max( Math.min( ( event.clientY - this.progressBarInner.getBoundingClientRect().top ) / this.progressBarHeight, 1 ), 0 );
progress = Math.max( Math.min( progress, 1 ), 0 );
this.viewportElement.scrollTop = progress * ( this.viewportElement.scrollHeight - this.viewportElement.offsetHeight );
};
const handleDocumentMouseUp = ( event ) => {
document.removeEventListener( 'mousemove', handleDocumentMouseMove );
document.removeEventListener( 'mouseup', handleDocumentMouseUp );
};
this.progressBarInner.addEventListener( 'mousedown', handleMouseDown );
}
/** /**
* Deactivates the reader mode and restores the standard slide-based * Deactivates the reader mode and restores the standard slide-based
* presentation. * presentation.
@@ -177,7 +133,7 @@ export default class Reader {
this.viewportElement.removeEventListener( 'scroll', this.onScroll ); this.viewportElement.removeEventListener( 'scroll', this.onScroll );
this.viewportElement.classList.remove( 'reveal-reader' ); this.viewportElement.classList.remove( 'reveal-reader' );
this.progressBar.remove(); this.removeProgressBar();
this.Reveal.getSlidesElement().innerHTML = this.slideHTMLBeforeActivation; this.Reveal.getSlidesElement().innerHTML = this.slideHTMLBeforeActivation;
this.Reveal.sync(); this.Reveal.sync();
@@ -324,7 +280,76 @@ export default class Reader {
return page; return page;
} ); } );
if( config.readerScrollBar ) {
this.createProgressBar();
this.createProgressBarSlides(); this.createProgressBarSlides();
}
else {
this.removeProgressBar();
}
}
createProgressBar() {
if( this.progressBar ) return;
this.progressBar = document.createElement( 'div' );
this.progressBar.className = 'reader-progress';
this.progressBarInner = document.createElement( 'div' );
this.progressBarInner.className = 'reader-progress-inner';
this.progressBar.appendChild( this.progressBarInner );
this.progressBarPlayhead = document.createElement( 'div' );
this.progressBarPlayhead.className = 'reader-progress-playhead';
this.progressBarInner.appendChild( this.progressBarPlayhead );
this.viewportElement.insertBefore( this.progressBar, this.viewportElement.firstChild );
const handleMouseDown = ( event ) => {
event.preventDefault();
this.draggingProgressBar = true;
document.addEventListener( 'mousemove', handleDocumentMouseMove );
document.addEventListener( 'mouseup', handleDocumentMouseUp );
handleDocumentMouseMove( event );
};
const handleDocumentMouseMove = ( event ) => {
let progress = ( event.clientY - this.progressBarInner.getBoundingClientRect().top ) / this.progressBarHeight;
progress = Math.max( Math.min( progress, 1 ), 0 );
this.viewportElement.scrollTop = progress * ( this.viewportElement.scrollHeight - this.viewportElement.offsetHeight );
};
const handleDocumentMouseUp = ( event ) => {
this.draggingProgressBar = false;
this.showProgressBar();
document.removeEventListener( 'mousemove', handleDocumentMouseMove );
document.removeEventListener( 'mouseup', handleDocumentMouseUp );
};
this.progressBarInner.addEventListener( 'mousedown', handleMouseDown );
}
removeProgressBar() {
if( this.progressBar ) {
this.progressBar.remove();
this.progressBar = null;
}
} }
@@ -377,12 +402,34 @@ export default class Reader {
moveProgressBarTo( progress ) { moveProgressBarTo( progress ) {
if( this.progressBar ) {
this.progressBarPlayhead.style.transform = `translateY(${progress * this.progressBarScrollableHeight}px)`; this.progressBarPlayhead.style.transform = `translateY(${progress * this.progressBarScrollableHeight}px)`;
this.pages.forEach( ( page ) => { this.pages.forEach( ( page ) => {
page.progressBarSlide.classList.toggle( 'active', !!page.active ); page.progressBarSlide.classList.toggle( 'active', !!page.active );
} ); } );
this.showProgressBar();
}
}
showProgressBar() {
this.progressBar.classList.add( 'visible' );
clearTimeout( this.hideProgressBarTimeout );
if( this.Reveal.getConfig().readerScrollBar === 'auto' && !this.draggingProgressBar ) {
this.hideProgressBarTimeout = setTimeout( () => {
this.progressBar.classList.remove( 'visible' );
}, HIDE_SCROLLBAR_TIMEOUT );
}
} }
scrollToSlide( slideElement ) { scrollToSlide( slideElement ) {