一、需求场景描述

1.先看演示效果

类似这种,当也页面左侧内容滚动的时候,需要关联激活左侧导航节点;当点击右侧导航节点时, 也会将左侧对应的内容滚动到可视区域顶部的场景,并不少见,比如知识类社区,掘金查看文章时,百度查看百科词条时,都有这种场景,而我的实际开发种也遇到此类需求。遂有此文。

2.需求分解

  • 1.滚动左侧内容,关联激活右侧导航节点
  • 2.单击右侧导航节点,右侧相应的段落滚动到可视区顶部

二、关键技术点提前知

技术点1:Element.scrollIntoView()

1.scrollIntoView() 的作用

scrollIntoView()方法会滚动元素的父容器,使被调用scrollIntoView()的元素对用户可见。

2.基本用法介绍:

var el = document.getElementById("p1");
// true 可以省略效果相同
el.scrollIntoView(true)

// alignToTop:Boolean型参数。
// 如果为 true,元素的顶端将和其所在滚动区的可视区域的顶端对齐。
// 如果为 false,元素的底端将和其所在滚动区的可视区域的底端对齐。
el.scrollIntoView(false);

// 可选,scrollIntoViewOptions:{behavior: "smooth", block: "end", inline: "nearest"}
// 可选,behavior :定义动画过渡效果,"auto"或 "smooth" 之一。默认为 "auto"。
// 可选,block:定义垂直方向的对齐,"start", "center", "end", 或 "nearest"之一。默认为 "start"。
// 可选,inline:定义水平方向的对齐,"start", "center", "end", 或 "nearest"之一。默认为 "nearest"。
el.scrollIntoView({behavior: "smooth", block: "end", inline: "nearest"});
el.scrollIntoView({block: "end"});

3.注意事项

普通的布局没问题,但是要注意,取决于其它元素的布局情况,此元素可能不会完全滚动到顶端或底端。比如整体上已经到顶部了,无法再滚动,那么该元素就不会移动到可视区的顶部。

技术点2:Element.getBoundingClientRect()

Element.getBoundingClientRect() 方法返回元素的大小及其相对于视口的位置。返回值是一个 DOMRect 对象,这个对象是由该元素的 getClientRects() 方法返回的一组矩形的集合,就是该元素的 CSS 边框大小。返回的结果是包含完整元素的最小矩形,并且拥有left, top, right, bottom, x, y, width, 和 height这几个以像素为单位的只读属性用于描述整个边框。除了width 和 height 以外的属性是相对于视图窗口的左上角来计算的。

下面是它的打印信息示例:

console.dir(document.getElementById("p1").getBoundingClientRect())

如果是标准盒子模型,元素的尺寸等于width/height + padding + border-width的总和。如果box-sizing: border-box,元素的的尺寸等于 width/height。

三、实现思路分析

1.数据初始化处理

// 从内容数据list中,获取段落标题作为导航标题。并为导航节点增加href,以段落的id值作为href的值
this.list.map((item, i) => {
  this.activities.push({title: item.title, act: false, href: "#p" + i});
});

2.监听滚动条,以便滚动内容时,关联激活右侧导航标签

// 监听滚动条
window.addEventListener("scroll", function (e) {
  // 防抖动处理
  clearTimeout(that.timeout)
  this.timeout = setTimeout(() => {
    that.activeNavNode(e)
  }, 100)
});

3.实现点击右侧导航节点,关联左侧内容滚动到可视区顶部

// dom中定位导航
navToPosition(item, index) {
  // 激活相应的导航节点,变色
  this.active = index;
  // 根据导航节点的href信息即id信息,获取对应的元素节点,通过 scrollIntoView 滚动该元素到可视区顶部
  document.querySelector(item.href).scrollIntoView(true);
},

4.实现滚动右侧内容,关联激活左侧导航节点

// 激活左侧对应的导航条
activeNavNode(e) {
  const nodes = document.getElementsByTagName("section")
  for (let i = 0; i < nodes.length; i++) {
    let node = nodes[i];
    // 获取该元素此时相对于视口的顶部的距离,即是元素顶部距离视口屏幕上边的距离
    let nodeY = node.getBoundingClientRect().y
    // 当元素距离视口顶部的距离在 [0,200] 之间,设置激活该元素对应左侧的导航标题,这个数字可以按需定义
    // 这里关联内容和导航标签,是巧妙利用了内容在元素集合中的索引序号和导航标签中的一致
    // 即是 list 和 activities 和 nodes 中下标相等的元素,具有对应关联的关系
    if (nodeY <= 200 && nodeY >= 0) {
      this.active = Number(i)
      return
    }
  }
},

四、完整 demo 示例代码

到此这篇关于JavaScript实现内容滚动与导航标签互动关联方案的文章就介绍到这了,更多相关JS内容滚动 内容请搜索阿兔在线工具以前的文章或继续浏览下面的相关文章希望大家以后多多支持阿兔在线工具!

点赞(1)

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部