丝滑导航滚动实现 | 实践记录以及工具使用

47 阅读2分钟

一、前情提要

最近,我正在全力投入到一个前端项目的开发工作当中。这个项目原本是有一个模板的,在这个模板里存在一个语言选择栏。然而,领导提出了新的要求,希望我能够对这个语言选择栏进行改造,将其变成一个导航栏。这个导航栏需要具备一个特殊的功能,那就是当用户点击导航栏中的某个选项时,页面能够通过相应的 id 精准地滚动到合适的位置,从而为用户提供更加便捷的浏览体验。 image.png

这原来是模板自带的一个语言选择栏,领导要我把它改造成导航栏,能够通过id滚动到合适的地方。

二、具体实现 在改造的初期,我采用了比较简单直接的方法,仅仅使用了 a 标签来实现跳转功能。但实际效果却不尽如人意,整个跳转过程显得十分生硬,没有达到预期的流畅度和用户体验。于是,我开始寻找新的解决方案。 经过一番研究和尝试,我使用了 CSS 样式来优化这个导航栏的滚动效果。具体的 CSS 代码如下:

<style>
    html {
       scroll-behavior: smooth;
    }

    /* 可选:为目标元素添加一些过渡效果 */
    [id] {
       scroll-margin-top: 30vh;
       transition: all 0.5s ease-in-out;
    }
</style>

来实现

在这段代码中,scroll - behavior: smooth;这一属性的设置使得页面滚动变得平滑,给用户一种流畅的视觉感受。而对于[id]选择器下的scroll - margin - top: 30vh;,这里的scroll - margin - top其实是用来控制滚动位置距离页面最上方的大小,其中vh是一个相对于电脑屏幕高度的单位,这里设置为30vh,意味着滚动到目标位置时,目标元素距离页面顶部的距离是屏幕高度的 30%。同时,transition: all 0.5s ease - in - ou

document.addEventListener('DOMContentLoaded', function() {
  document.body.addEventListener('click', function(e) {
    // 检查点击的是否为锚点链接
    if (e.target.tagName === 'A' && e.target.hash) {
      e.preventDefault(); // 阻止默认行为
      var targetId = e.target.hash.slice(1);
      var targetElement = document.getElementById(targetId);

      if (targetElement  && targetId !== 'menu') {
        // 计算目标元素的位置
        var elementRect = targetElement.getBoundingClientRect();
        var absoluteElementTop = elementRect.top + window.pageYOffset;
        // 将目标位置设置为视窗高度的40%处(中间偏上)
        var offsetPosition = absoluteElementTop - (window.innerHeight * 0.3);

        // 平滑滚动到目标位置
        window.scrollTo({
          top: offsetPosition,
          behavior: 'smooth'
        });
      }
    }
  });
});

在这段 JavaScript 代码中,首先通过document.addEventListener('DOMContentLoaded', function() {...})来确保在文档加载完成后执行后续的代码。然后,为document.body添加了一个点击事件监听器。当用户点击页面时,代码会检查点击的元素是否是一个带有hash值的a标签(即锚点链接)。如果是,就会阻止默认的跳转行为。接着,获取锚点链接指向的目标元素的 id,并通过document.getElementById(targetId)获取目标

放不了视频。。。不过大家可以去尝试一下