我有 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>
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
如果我正确理解您的问题,我认为您可以将最后一个案例的半高添加到
maxTop计算中,如下所示:let { height: lastCaseHeight } = cases[cases.length - 1].getBoundingClientRect(); maxTop = maxTop + (lastCaseHeight / 2)这样,圆的最大顶部位置将位于最后一个案例的中间。请检查更新的代码片段: