我有 3 个块,第二个块有一条线和一个滚动圆。圆圈会随着主滚动一起滚动,当滚动停止时,圆圈会粘到最近的点,即每个块的中心
但是我在这里遇到这样的问题,当主滚动穿过第二个块时,圆圈停止滚动并且在页面上表现不正确
是否可以完成脚本,以便当主滚动穿过 block2
时,圆圈将自动坚持最后一个案例并完全停止滚动?当我们返回并穿过 block2
时,相应地,它应该再次工作
一般来说,问题在于最后一种情况,当滚动到达它时,圆圈不会进一步移动,也许还有另一种解决方案,而不是我建议的选项
我需要从block2
开始到结束的滚动是平滑的,并且当滚动停止时,圆圈应该粘在最近的案例的中心
在我的示例中,这就是现在发生的情况,如果您停止滚动,那么它会停留在需要的位置,但对我来说它不会正确滚动到末尾
const circle = document.querySelector(".circle"); const cases = document.querySelectorAll(".case"); let timer = null; const detectCase = () => { const circleCenter = circle.offsetTop + circle.offsetHeight / 2; let activeCase = null, minDist = Infinity; cases.forEach((elem) => { const caseCenter = elem.offsetTop + elem.offsetHeight / 2; const dist = Math.abs(caseCenter - circleCenter); if (dist < minDist) { minDist = dist; activeCase = elem; } }); return activeCase; }; const handleScroll = () => { const { height: blockHeight } = document.querySelector(".block2").getBoundingClientRect(); const maxTop = cases[cases.length - 1].offsetTop; const minTop = cases[0].offsetTop; let { height: startTop } = cases[0].getBoundingClientRect(); let scrollDist = startTop / 2 + window.scrollY; scrollDist = scrollDist > maxTop ? maxTop : scrollDist < minTop ? minTop : scrollDist; circle.style.top = `${scrollDist}px`; circle.style.backgroundSize = `15px ${blockHeight}px`; circle.style.backgroundPosition = `0 ${-scrollDist}px`; if (timer) return; timer = setTimeout(() => { const active = detectCase(); const activePos = active.offsetTop + active.offsetHeight / 2; circle.style.top = `${activePos}px`; circle.style.backgroundPosition = `0 ${-activePos}px`; circle.style.transition = "0.5s"; timer = null; }, 800); circle.style.transition = ""; }; const handleWindowSize = () => { if (window.innerWidth >= 991) { window.addEventListener("scroll", handleScroll); window.addEventListener("resize", handleScroll); } else { window.removeEventListener("scroll", handleScroll); window.removeEventListener("resize", handleScroll); } }; handleScroll(); handleWindowSize(); window.addEventListener("resize", handleWindowSize);
.block1 { height: 200px; background-color: gray; } .block3 { height: 600px; background-color: gray; } .block2 { height: 100%; position: relative; } .block2, .block2 .circle { background: linear-gradient(214deg, rgba(79, 142, 255, 0) 0%, #4f8eff 10%, #f5e550 90%, rgba(79, 142, 255, 0) 100%) center/3px calc(100% - 100px) no-repeat; } .block2 .circle { width: 15px; height: 15px; left: calc(50% - 8px); } .block2 .circle, .block2 .circle::before { position: absolute; border-radius: 50%; } .block2 .circle::before { content: ""; inset: 3px; background-color: white; } .text { text-align: center; padding: 200px 50px; }
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css" integrity="sha512-t4GWSVZO1eC8BM339Xd7Uphw5s17a86tIZIj8qRxhnKub6WoyhnrxeCIMeAqBPgdZGlCcG2PrZjMc+Wr78+5Xg==" crossorigin="anonymous" referrerpolicy="no-referrer" /> <div class="block1"></div> <div class="block2"> <div class="circle"></div> <div class="case"> <div class="row"> <div class="col-5 text">Text 1</div> <div class="col-2"></div> <div class="col-5 text">Text 1</div> </div> </div> <div class="case"> <div class="row"> <div class="col-5 text">Text 2</div> <div class="col-2"></div> <div class="col-5 text">Text 2</div> </div> </div> <div class="case"> <div class="row"> <div class="col-5 text">Text 3</div> <div class="col-2"></div> <div class="col-5 text">Text 3</div> </div> </div> </div> <div class="block3"></div>
如果我正确理解您的问题,我认为您可以将最后一个案例的半高添加到
maxTop
计算中,如下所示:这样,圆的最大顶部位置将位于最后一个案例的中间。请检查更新的代码片段: