Skip to content

给 Astro 增加脚注跳回时的引用位置提示

更新于: at 16:30

内容目录

痛点

在文章内容中包含脚注 1 后,对脚注感兴趣的读者会点击脚注以跳转到文末阅读注释,当脚注阅读完成后,再点击回到原位置继续阅读。此时,若脚注链接颜色不是很明显,读者会失去阅读焦点,从而给继续阅读造成障碍。

解决方案

本文提供解决方案是:当检测到读者是从脚注跳回时,给读者一个原脚注引用位置的提示。

具体实现思路为:检测到用户点击脚注返回原引用位置的过程中,当脚注锚链重新出现在浏览器的视口(Viewport)中后,闪烁此脚注引起注意。

实现方式

在 src\styles\base.css 末尾增加一个动画类 blinking

.blinking  {
  animation: blink .5s ease-in-out infinite;
}

@keyframes blink {
  0% {
    opacity: 1;
    background: black;
  }
  25% {
    opacity: 0;
    background: white;
  }
  50% {
    opacity: 1;
    background: black;
  }
  75% {
    opacity: 0;
    background: white;
  }
  100% {
    opacity: 1;
    background: black;
  }
}

在 src\layouts\Layout.astro 中增加处理事件,这里值得注意的是,由于 Astro Paper 主题异步加载文章,对于文章中脚注点击事件需要实现预绑定,即 DOM 元素未加载时先绑定点击事件,实现方式为在上级节点绑定点击事件,在点击后过滤节点。

<script is:inline>
  let timerAnchor;
  document.addEventListener("DOMContentLoaded", () => {
    document.addEventListener('click', function(e) {
      const links = document.getElementById('article').getElementsByTagName('a');
      for (let i = 0; i < links.length; i++) {
        const match = links[i].hash.match(/#(.*)-fnref-\d+$/);
        if (match) {
          links[i].onclick = function (event) {
            const target = event.srcElement || event.target;
            timerAnchor = setInterval(checkAnchorInViewport, 100, target.hash);
          };
        }
      }
    });
    
    function checkAnchorInViewport(hash) {
      const el = document.getElementById(hash.slice(1, hash.length));
      if (isElInViewport(el)) {
        clearInterval(timerAnchor);

        el.classList.add('blinking');
        setTimeout(() => { el.classList.remove('blinking'); }, 1000);
      }
    }

    function isElInViewport(element) {
      const rect = element.getBoundingClientRect();
      return (
        rect.top >= 0 &&
        rect.left >= 0 &&
        rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
        rect.right <= (window.innerWidth || document.documentElement.clientWidth)
      );
    }
  });
</script>

脚注

Footnotes

  1. 脚注:这个脚注的存在是为了方便体验本文实现的“脚注闪烁”效果,可以尝试点击最后的返回箭头。