如果您想依赖 scrollIntoView,您可以阻止用户滚动页面。
该函数尝试将给定元素滚动到视口中。
/* I did not post the complete implementation here to avoid plain copy *
* and paste and to allow for own (and better) implemantations - if *
* someone prefers to see the working implementation, I might edit the post. */
使用 scrollIntoView 锁定页面
所以问题是:你想滚动到哪个元素? PDF.js 有一个名为 viewer 的元素——它有很多子元素,因为加载的 PDF 有页面。
例如,第三个孩子持有 PDF 的第三页。
下一个问题:何时您想将其滚动到视图中?这看起来有点难。我们可以通过在该元素上运行getClientRects() 来从它的DOMRect 中获取元素的顶部位置。如果顶部大于视口的顶部边框,我们就向外滚动。
对于底部,它有些相同:元素的可见部分(关于高度)是它的高度减去隐藏部分(即在视口顶部之外)。如果height - hiddenPart
假设一个元素存储在pc(页面容器)中,将上述两者结合起来,您将拥有:
function lockToPage() {
var rect = pc.getClientRects()[0];
var offsetNav = vc.offsetTop;
if (rect.y > offsetNav) { pc.scrollIntoView(true); }
if (rect.height + rect.y - window.innerHeight < 0) { pc.scrollIntoView(false); }
}
vc 是视图容器,它又包含所有页面容器 - 考虑到它的偏移量,因为(在 PDF.js 中)我们可能有一个可见的导航栏。
这里的页面被锁定的方式不是很好,因为试图滚动到元素之外会使页面振动。
忽略这个故障,我们如何知道要锁定到哪个页面(元素)?
好吧,这很简单,因为我们有 PDFViewerApplication.page 用于页面和
vc.children[pageIndex] 用于我们的页面容器。从那里开始,我们所要做的就是收听pagechange 来更新当前页面。
以下是我们如何将所有锁定组合在一起:
function initLocker() {
vc = document.getElementById("viewerContainer");
pc = document.getElementById("page1").offsetParent;
lockToPage();
vc.addEventListener("scroll", lockToPage);
}
释放这样的锁将通过从vc中移除事件监听器来执行;但是什么时候应该做呢?嗯,十秒后……换页后?没有。由于某些页面可能需要一些时间来渲染,我们最好等待页面完成渲染,然后收听pagerendered。
我们要添加的小东西是防止用户跳过页面并在我们完成设置之前阻止用户交互。
现在我们已经有了我们需要的一切,我猜 - 获取我们的 PDF.js 源 (viewer.html),我们可以添加我们的代码 之前 其他 JS 包含以确保我们的事件侦听器将先附上,见SO on multiple event listeners