目录
演示
编辑
需求
代码
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)();});