published on in Go

自制PDF阅读器・显示页码

上次我们使用 go-fitz 实现了一个 PDF 阅读器,虽然它可以正常翻页,但是却不显示页面号码,有的时候我们想按照学习计划每天阅读某书N页,如果不显示页码就会对阅读体验造成负面影响。为此,今天我们给它加上页面号码显示功能。

HTML 前端内容

我们增加一段 html 内容到特定位置:

</head>
<body>
<div id="progress" style="position:fixed;z-index:1000;color:white"></div>
<div id="pages"></div>
</body>
<script charset="utf-8">

注意:这里我们新增的内容是:

<div id="progress" style="position:fixed;z-index:1000;color:white"></div>

我们将在这个 DIV 的位置显示页码。

JS脚本

我们使用IntersectionObserver工具来监听页面元素进入视图,当元素与视图相交达到阈值threshold时「这里为0.5」就会触发事件的回调函数,我们在回调函数中设置并显示页面号码:

const observer = new IntersectionObserver(entries => {
	// entries 是一个包含一个或多个 IntersectionObserverEntry 条目的数组
	entries.forEach(entry => {
		// isIntersecting 属性指示元素是否与视口相交
		if (entry.isIntersecting) {
			// 元素已进入视图
			document.querySelector('#progress').innerHTML = (
				'page:' + entry.target.id.substr('page'.length));
		}
	});
}, {
	threshold: 0.5,
});

上述代码在load_page函数中实现:

async function load_page(position, page_ix=-1) {
    const pages = document.querySelector('#pages');
    if (page_ix == -1) {
        if (position == 'beforeEnd') {
            page_ix = Number(
                pages.lastElementChild.id.substr('page'.length)) + 1;
        } else if (position == 'afterBegin') {
            page_ix = Number(
                pages.firstElementChild.id.substr('page'.length)) - 1;
        }
    }
    const url = '/page?ix=' + page_ix;
    const resp = await fetch(url);
    if (!resp.ok) {
        return;
    }
    const page = await resp.text()
    pages.insertAdjacentHTML(position, page);
    const observer = new IntersectionObserver(entries => {
        // entries 是一个包含一个或多个 IntersectionObserverEntry 条目的数组
        entries.forEach(entry => {
            // isIntersecting 属性指示元素是否与视口相交
            if (entry.isIntersecting) {
                // 元素已进入视图
                document.querySelector('#progress').innerHTML = (
                    'page:' + entry.target.id.substr('page'.length));
            }
        });
    }, {
        threshold: 0.5,
    });
    if (position == 'afterBegin') {
        window.scrollTo(0, pages.firstChild.offsetHeight);
        observer.observe(pages.firstElementChild);
    } else if (position == 'beforeEnd') {
        observer.observe(pages.lastElementChild);
    }
}

注意我们需要根据参数position设置不同位置的观测对象:

    if (position == 'afterBegin') {
        window.scrollTo(0, pages.firstChild.offsetHeight);
        observer.observe(pages.firstElementChild);
    } else if (position == 'beforeEnd') {
        observer.observe(pages.lastElementChild);
    }

以上就完成了我们需要的页面显示功能,可以尝试运行看看效果: