目錄
演示
?編輯
需求
代碼
css
html
script
代碼解釋
1、獲取所有link-content
2、定義一個rectContent數組,然后循環allContents調用getClientRects()[0]獲取每個link-content元素與瀏覽器視口的關系
3、為數組追加link-content,用于設置側邊欄高亮
情況1
情況2
4、設置高亮
5、添加節流,減少觸發回調的頻率
演示
需求
左側側邊欄link1、link2...所對應右側內容link1-content、link2-content...,當鼠標點擊link的時候,自動滾動到對應的content。手動拖動滾動條,左側link進行高亮響應,當link2-content出現在視口的時候,左側link2高亮,當link2-content和link3-content同時出現在視口的時候,左側link2高亮(誰接近視口頂部,對應的link高亮)。
代碼
css
* {padding: 0;margin: 0;list-style: none;}.header {height: 200px;background-color: aqua;}.main {padding: 30px 0;display: flex;max-width: 1400px;margin: 0 auto;gap: 30px;}.main .sidebar {position: sticky;top: 0;width: 300px;align-self: start;}.main .content {display: flex;flex: 1;flex-direction: column;gap: 30px;}.main .content .content-item{background-color: aqua;height: 400px;}.main .sidebar ul li{padding: 20px 10px;background-color: aqua;}.main .sidebar ul li .active{color: red;}.footer {height: 200px;background-color: aqua;}
html
<body><section class="header"></section><section class="main"><div class="sidebar"><ul><li><a class="active" href="#content-item1">link1</a></li><li><a href="#content-item2">link2</a></li> // 設置錨點所對應的content的id<li><a href="#content-item3">link3</a></li><li><a href="#content-item4">link4</a></li><li><a href="#content-item5">link5</a></li><li><a href="#content-item6">link6</a></li></ul></div><div class="content"><div id="content-item1" class="content-item">link1-content</div><div id="content-item2" class="content-item">link2-content</div><div id="content-item3" class="content-item">link3-content</div><div id="content-item4" class="content-item">link4-content</div><div id="content-item5" class="content-item">link5-content</div><div id="content-item6" class="content-item">link6-content</div></div></section><section class="footer"></section></body>
script
const allLinks = document.querySelectorAll("a:link");allLinks.forEach(function (link) {link.addEventListener("click", function (e) {e.preventDefault();const href = link.getAttribute("href");if ( href.startsWith("#")) {const sectionEl = document.querySelector(href);link_content.scrollIntoView({ behavior: "smooth" });}});});
設置link的href和link-content的id所對應,調用scrollIntoView({ behavior: "smooth" })自動滾動到對應的位置。
const handleScroll = () => {const allContents = document.querySelectorAll(".content-item");const rectContent = [];allContents.forEach((ele) => {const eleRect = ele.getClientRects()[0];if (eleRect.top >= 0 &&window.innerHeight - eleRect.top >= eleRect.height) {rectContent.push(ele);} else if (eleRect.top >= 0) {rectContent.push(ele);}});let linkIdif (rectContent[0]) linkId = rectContent[0].idallLinks.forEach(link => link.classList.remove('active'))const linkDom = document.querySelector(`a[href="#${linkId}"]`)linkDom.classList.add('active')}window.addEventListener("scroll", function() {throttle(handleScroll, 100)();});window.addEventListener('mouseup', function() {throttle(handleScroll, 100)();});
代碼解釋
瀏覽器滾動,每次滾動觸發scroll回調
1、獲取所有link-content
2、定義一個rectContent數組,然后循環allContents調用getClientRects()[0]獲取每個link-content元素與瀏覽器視口的關系
3、為數組追加link-content,用于設置側邊欄高亮
往數組追加值分兩種情況
情況1
link-content1和link-content2都完全出現在視口中,誰接近視口頂部,對應的link高亮
情況2
都沒有出現在視口中,則取出現在視口第一個與視口頂部,top > 0的值
4、設置高亮
let linkIdif (rectContent[0]) linkId = rectContent[0].idallLinks.forEach(link => link.classList.remove('active'))const linkDom = document.querySelector(`a[href="#${linkId}"]`)linkDom.classList.add('active')
找到存儲在數組的第一項link-content,獲取id,根據id獲取對應的側邊欄link,清空之前設置的link的類active,為對應的link添加類active。
5、添加節流,減少觸發回調的頻率
const throttle = (fn, delay) => {let lastExecuted = 0;return function() {const now = Date.now();if (now - lastExecuted > delay) {fn();lastExecuted = now;}}}window.addEventListener("scroll", function() {throttle(handleScroll, 100)();});window.addEventListener('mouseup', function() {throttle(handleScroll, 100)();});