diff --git a/packages/epubjs/src/managers/default/index.js b/packages/epubjs/src/managers/default/index.js index cbc0311c..6406c560 100644 --- a/packages/epubjs/src/managers/default/index.js +++ b/packages/epubjs/src/managers/default/index.js @@ -481,13 +481,24 @@ class DefaultViewManager { ) { this.scrollLeft = this.container.scrollLeft - left = - this.container.scrollLeft + - this.container.offsetWidth + - this.layout.delta + // `offsetWidth` includes borders while `scrollWidth` and `clientWidth` + // describe the inner scrollable area. Mixing them can make the last + // page unreachable because of rounding or border-width differences. + const maxScrollLeft = Math.max( + 0, + this.container.scrollWidth - this.container.clientWidth, + ) + const epsilon = 1 + const currentPage = Math.round( + this.container.scrollLeft / this.layout.delta, + ) - if (left <= this.container.scrollWidth) { - this.scrollBy(this.layout.delta, 0, true) + if (this.container.scrollLeft < maxScrollLeft - epsilon) { + this.scrollTo( + Math.min((currentPage + 1) * this.layout.delta, maxScrollLeft), + 0, + true, + ) } else { next = this.views.last().section.next() } @@ -585,8 +596,9 @@ class DefaultViewManager { left = this.container.scrollLeft - if (left > 0) { - this.scrollBy(-this.layout.delta, 0, true) + const currentPage = Math.round(left / this.layout.delta) + if (currentPage > 0) { + this.scrollTo((currentPage - 1) * this.layout.delta, 0, true) } else { prev = this.views.first().section.prev() } @@ -675,7 +687,10 @@ class DefaultViewManager { } } else { this.scrollTo( - this.container.scrollWidth - this.layout.delta, + Math.max( + 0, + this.container.scrollWidth - this.container.clientWidth, + ), 0, true, ) @@ -839,9 +854,13 @@ class DefaultViewManager { ) let totalPages = this.layout.count(width).pages - let startPage = Math.floor(start / this.layout.pageWidth) + // Treat sub-pixel and border rounding near a page boundary as that page. + const positionEpsilon = 1 + let startPage = Math.floor( + (start + positionEpsilon) / this.layout.pageWidth, + ) let pages = [] - let endPage = Math.floor(end / this.layout.pageWidth) + let endPage = Math.floor((end + positionEpsilon) / this.layout.pageWidth) // start page should not be negative if (startPage < 0) {