繁体   English   中英

如何使用 Intersection Observer API 获取所有条目?

[英]How to get all entries using Intersection Observer API?

我想让左侧导航显示当前可见部分。 但是我的部分有不同的高度,我不知道如何正确跟踪它们。

如果每次调用我的回调函数都可以看到所有条目及其状态,但它会获取与阈值匹配的条目,那就更好了。

我可能错过了一些东西。 应该有一种方法可以使这个工作。

这是我的 jsBin https://jsbin.com/homibef/edit?html,css,js,output

 stickybits('#sticky', { stickyBitStickyOffset: 0 }); if (window.IntersectionObserver) { const callback = function(entries) { // Find all visible and then with biggest intersectionRatio let currentNav = null; const visibleEntries = entries.filter(entry => entry.isIntersecting); if ( Array.isArray(visibleEntries) && visibleEntries.length > 0 ) { currentNav = visibleEntries.reduce((prev, current) => { return (prev.intersectionRatio > current.intersectionRatio) ? prev : current; }); } else { currentNav = visibleEntries; } if (currentNav.target) { // Handle navigation change const wasCurrent = document.querySelector('.navItem.isCurrent'); if ( wasCurrent ) { wasCurrent.classList.remove('isCurrent'); } const currentName = currentNav.target.getAttribute('name'); const current = document.querySelector(`.navItem[data-link='${currentName}']`); current.classList.add('isCurrent'); } }; const observer = new IntersectionObserver(callback, { root: null, rootMargin: '0px', threshold: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1], }); const section = document.querySelectorAll('section'); section.forEach(item => observer.observe(item)); }
 * { margin: 0; padding: 0; } .row { width: 100%; display: flex; flex-wrap: nowrap; } .navigation { margin-right: 50px; } .navItem { color: #666; } .navItem.isCurrent { font-weight: bold; color: #000; } .content { width: 100%; flex: 1; } section { padding: 10px; width: 200px; border-radius: 10px; margin-bottom: 30px; } .section1 { height: 800px; background: #90ee90; } .section2 { height: 200px; background: #add8e6; } .section3 { height: 150px; background: #808080; } .section4 { height: 400px; background: #800080; }
 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>JS Bin</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/stickybits/3.7.3/stickybits.min.js"></script> </head> <body> <div class="row"> <!-- Navigation --> <div class="navigation"> <div id="sticky" class="sticky"> <ul class="nav"> <li data-link="section1" class="navItem">Section 1</li> <li data-link="section2" class="navItem">Section 2</li> <li data-link="section3" class="navItem">Section 3</li> <li data-link="section4" class="navItem">Section 4</li> </ul> </div> </div> <!-- Content --> <div class="content"> <section name="section1" class="section1"></section> <section name="section2" class="section2"></section> <section name="section3" class="section3"></section> <section name="section4" class="section4"></section> </div> </div> </body> </html>

这有点棘手,但它应该像你描述的那样工作。 javascript评论中的更多信息:

 stickybits('#sticky', { stickyBitStickyOffset: 0 }); if (window.IntersectionObserver) { const section = document.querySelectorAll('section'); const sectionArr = Array.from(section); const callback = function(entries) { // this is intialized for all targets // after that, only entries which pass threshold(any) in same viewport position(scroll) // thus it will be most likely one or two sections, not all for (entry of entries) { // setting properties on native Objects is ugly, but most straightforward // instead of intersectionRatio, we want intersectionRect to compare height // more tresholds => more precise behaviour // step 0.1 = 10%, 10% of 3000px height section = 300px => pretty large breakpoints entry.target._intersectionHeight = entry.intersectionRect.height; } // compare visibility of sections(all) after every intersection const mostVisibleSection = sectionArr.reduce((prev, current) => { if (current._intersectionHeight > (prev ? prev._intersectionHeight : 0)) { return current; } else { return prev; } }, null); // TIP: you can store this variable outside of callback instead of selecting const prevMostVisibleLink = document.querySelector('.isCurrent'); // no section is visible if (!mostVisibleSection) { prevMostVisibleLink && prevMostVisibleLink.classList.remove('isCurrent'); return; } // ok, there is most visible section, lets target link const mostVisibleLink = document.getElementById(mostVisibleSection.dataset.id); if (mostVisibleLink !== prevMostVisibleLink) { prevMostVisibleLink && prevMostVisibleLink.classList.remove('isCurrent'); mostVisibleLink.classList.add('isCurrent'); } }; // zero covers also entries comming out of viewport const observer = new IntersectionObserver(callback, { threshold: [0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1], }); section.forEach(item => observer.observe(item)); }
 * { margin: 0; padding: 0; } .row { width: 100%; display: flex; flex-wrap: nowrap; } .navigation { margin-right: 50px; } .navItem { color: #666; } .navItem.isCurrent { font-weight: bold; color: #000; } .content { width: 100%; flex: 1; } section { padding: 10px; width: 200px; border-radius: 10px; margin-bottom: 30px; } .section1 { height: 800px; background: #90ee90; } .section2 { height: 200px; background: #add8e6; } .section3 { height: 150px; background: #808080; } .section4 { height: 400px; background: #800080; }
 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>JS Bin</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/stickybits/3.7.3/stickybits.min.js"></script> </head> <body> <div class="row"> <!-- Navigation --> <div class="navigation"> <div id="sticky" class="sticky"> <ul class="nav"> <li id="section1" class="navItem">Section 1</li> <li id="section2" class="navItem">Section 2</li> <li id="section3" class="navItem">Section 3</li> <li id="section4" class="navItem">Section 4</li> </ul> </div> </div> <!-- Content --> <div class="content"> <section name="section1" class="section1" data-id="section1"></section> <section name="section2" class="section2" data-id="section2"></section> <section name="section3" class="section3" data-id="section3"></section> <section name="section4" class="section4" data-id="section4"></section> </div> </div> </body> </html>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM