发布日期:Mar 19, 2019 更新日期: 2023-7-22文章字数 0阅读时长:0分钟

起因

有的网页页面,可以在页面滚动的时候,给 url 自动添加或者改变锚点,锚点内容即为当前页面正在显示的内容的分级标题。我希望自己的博客页面也能有这样的效果,这样的话,复制 url 的时候就可以带上锚点,打开后就能快速定位到需要查看的内容处。

分析

要实现这个功能,做到以下两点就可以了
  1. 判断位于当前浏览器视口顶部的元素属于哪一个分级标题的内容
  1. 将当前分级标题的 id 名作为锚点添加或修改到 url 尾部
打开控制台,可以看到,hexo next 的主题,通过 markdown 渲染出的内容,包含在 classpost-block 的元素中。
notion image
而所有的分级标题渲染出来后,会依次对应 htmlh1h6 标签,且 id 名与标题等同。(不过空格会被替换为 - )
notion image

实现

判断分级标题的内容

我们可以通过 Element.getBoundingClientRect().top 来获取一个 dom 元素的顶部与视口顶部的距离,如果得到一个负值,那么证明这个元素是在视口之上、或者正处于视口中。我们要的就是处于视口上的那个元素。获取它的 id 即可。

修改 URL,添加或者改变锚点内容

利用 HTML5 的历史记录 API,history.replaceState,它可以修改当前历史记录项,改变 url 信息,但却不会引起 url 跳转。

代码

// 按从上到下的先后顺序,获取 .post-body 里面所有的 h 标签 let hList = document.querySelectorAll('.post-body h1,.post-body h2,.post-body h3,.post-body h4,.post-body h5,.post-body h6'); let nowAnchor = null; let time = 0; window.addEventListener('scroll', function (e) { // 事件节流,每 100ms 进行一次判断 if (Date.now() - time >= 100) { // 逆向查找,找到的第一个负值所对应的元素即为我们需要的 for (let i = hList.length - 1; i >= 0; i--) { if (hList[i].getBoundingClientRect().top <= 0) { if (hList[i].id !== nowAnchor) { let href = location.href.includes('#') ? location.href.split('#')[0] : location.href; nowAnchor = hList[i].id; history.replaceState({}, '', `${href}#${nowAnchor}`); } break; } } time = Date.now(); } });

简单的网页数字变更动画实现 简单的网页数字变更动画实现

通常情况下,数字在网页中的变化是直接转变为另一个值。而如果在数字转化的过程中,每次改变一点点,最终转变为另一个值,会让干硬的网页变得更加生动一点。


复制页面内容添加版权声明 复制页面内容添加版权声明

现如今,如果你要直接复制简书、掘金、CSDN 等网站上文章的内容,当你粘贴的时候就会发现,复制的文字中多了几行版权信息。