1. 1. 前言
  2. 2. 实践
  3. 3. 最后

前言

很多博客中最常见的问题就是:文章很长,但是读者很忙。下次阅读的时候,可能要花一些时间才能恢复到先前的阅读位置。

如果可以设备间,识别二维码或是一个链接就可以让阅读无缝衔接,直接跳转到相应位置,那么阅读体验就会变得更加优秀。

那么,开始吧!

实践

要知道阅读位置,那么就要知道当前页面的坐标。

const getScrollPosition = (el = window) => ({
x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,
y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop
});
// getScollPosition().x => 页面横坐标; getScrollPosition().y => 页面纵坐标;

大部分情况下,我们只用关注纵坐标。横坐标大概率为 0

我们还需要一个页面滚动的事件,用于记录当前坐标,并储存在临时存储中。

至于为什么是 sessionStorage 而不是 localStorage,则是因为 localStorage 除手动清除外,不会自动过期。

// 此处的 750 是「页面元素的最大宽度」
var wx = window.innerWidth >= 750 ? 750 : window.innerWidth;
var wy = window.innerHeight;
function windowScroll() {
// 反复修改 确保页面尺寸不改变
wx = window.innerWidth >= 750 ? 750 : window.innerWidth;
wy = window.innerHeight;
let y = Math.round(getScrollPosition().y);
// 组合字符串,同时记录页面坐标,页面宽度和高度
let p = `${y}:${wx}:${wy}`;
// 写入到 sessionStorage 中
sessionStorage.setItem("read_y", p);
}
window.onscroll = windowScroll;

你可能发现了,此处的变量 p,并不仅仅是「页面纵坐标」,而是「页面高度」与「纵坐标」的组合字符串。

事实上,如果单纯是纵坐标判断位置,那么在不同高度,不同宽度的设备上,就会出现错位的情况。而同时记录三个信息,就可以还原真实坐标。

// URL 中是否包含传递的坐标信息
if (location.hash.split("#read=").length > 1) {
// 分离字符串
let read_y = location.hash.split("#read=")[1];
read_y = read_y.split(":");
// 组合乘积,顺滑移动至坐标
window.scrollTo({top: Math.round(Number(read_y[0]) * Number(read_y[1] * Number(read_y[2] / wx / wy))), behavior: "smooth"});
} else {
// 从 sessionStorage 中获取
let read_y = sessionStorage.getItem("read_y") || "0:0:0";
read_y = read_y.split(":");
window.scrollTo({top: Math.round(Number(read_y[0]) * Number(read_y[1] * Number(read_y[2] / wx / wy))), behavior: "smooth"});
}

到现在,我们已经完成了 URL 的解析和基本生成。

那么,URL 即为:

`${location.protocol}//${location.hostname}${location.port ? ":"+location.port:location.port}${location.pathname}#read=${sessionStorage.getItem("read_y")}`;

最后

搭配生成二维码等插件效果更佳。

Miracle 主题将在下个版本中更新该功能。