首頁 > 軟體

JavaScript實現內容捲動與導航標籤互動關聯方案

2022-06-07 14:02:26

一、需求場景描述

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內容捲動 內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com