停止滚动线在方块被穿越时滚动。

huangapple go评论80阅读模式
英文:

stop the scroll line from scrolling if the block is crossed

问题

我有3个块,第二个块上有一条线和一个滚动的圆圈。圆圈会随着主滚动一起滚动,当滚动停止时,圆圈会停在最近的点,即每个块的中心。

但我在这里遇到了一个问题,当主滚动穿过第二个块时,圆圈停止滚动,页面上的行为不正确。

是否可能完成脚本,以便当主滚动穿过block2时,圆圈会自动粘附到最后的位置并停止滚动?当我们再次上升并穿过block2时,它应该再次正常工作。

总之,问题出在最后一个情况,当滚动到达它时,圆圈不再移动,也许有另一种修复它的选项,而不是我提出的这种。

我希望滚动从block2的开头到结尾都是平滑的,当滚动停止时,圆圈应该粘附到最近情况的中心。

在我的示例中,现在的情况是,如果停止滚动,它会停在需要停止的地方,但对我来说它不会正确滚动到结尾。

英文:

I have 3 blocks, the second block has a line and a scrolling circle. The circle will scroll along with the main scroll, and when the scroll stops, the circle sticks to the nearest point, which is in the center of each block

But I have such a problem here, when the main scroll crosses the second block, the circle stops scrolling and behaves incorrectly on the page

Is it possible to complete the script so that when the main scroll crosses block2, the circle will automatically stick to the last case and stop scrolling at all? And when we rise back and cross block2, then, accordingly, it should work again

In general, the problem is with the last case, when the scroll reaches it, the circle does not move further, maybe there is another option how to fix it, and not the one I suggested

I need the scroll to be smooth from the beginning of block2 to the end, and when the scroll stops, the circle should stick to the center of the nearest case

In my example, this is what happens now, if you stop scrolling, then it sticks where it needs to, but it doesn’t scroll correctly to the end for me

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const circle = document.querySelector(&quot;.circle&quot;);
const cases = document.querySelectorAll(&quot;.case&quot;);
let timer = null;

const detectCase = () =&gt; {
  const circleCenter = circle.offsetTop + circle.offsetHeight / 2;
  let activeCase = null,
    minDist = Infinity;
  cases.forEach((elem) =&gt; {
    const caseCenter = elem.offsetTop + elem.offsetHeight / 2;
    const dist = Math.abs(caseCenter - circleCenter);
    if (dist &lt; minDist) {
      minDist = dist;
      activeCase = elem;
    }
  });
  return activeCase;
};

const handleScroll = () =&gt; {
  const {
    height: blockHeight
  } = document.querySelector(&quot;.block2&quot;).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 &gt; maxTop ? maxTop : scrollDist &lt; 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(() =&gt; {
    const active = detectCase();
    const activePos = active.offsetTop + active.offsetHeight / 2;
    circle.style.top = `${activePos}px`;
    circle.style.backgroundPosition = `0 ${-activePos}px`;
    circle.style.transition = &quot;0.5s&quot;;
    timer = null;
  }, 800);
  circle.style.transition = &quot;&quot;;
};

const handleWindowSize = () =&gt; {
  if (window.innerWidth &gt;= 991) {
    window.addEventListener(&quot;scroll&quot;, handleScroll);
    window.addEventListener(&quot;resize&quot;, handleScroll);
  } else {
    window.removeEventListener(&quot;scroll&quot;, handleScroll);
    window.removeEventListener(&quot;resize&quot;, handleScroll);
  }
};

handleScroll();
handleWindowSize();
window.addEventListener(&quot;resize&quot;, handleWindowSize);

<!-- language: lang-css -->

.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: &quot;&quot;;
  inset: 3px;
  background-color: white;
}

.text {
  text-align: center;
  padding: 200px 50px;
}

<!-- language: lang-html -->

&lt;link rel=&quot;stylesheet&quot; href=&quot;https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css&quot; integrity=&quot;sha512-t4GWSVZO1eC8BM339Xd7Uphw5s17a86tIZIj8qRxhnKub6WoyhnrxeCIMeAqBPgdZGlCcG2PrZjMc+Wr78+5Xg==&quot; crossorigin=&quot;anonymous&quot; referrerpolicy=&quot;no-referrer&quot;
/&gt;
&lt;div class=&quot;block1&quot;&gt;&lt;/div&gt;
&lt;div class=&quot;block2&quot;&gt;
  &lt;div class=&quot;circle&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;case&quot;&gt;
    &lt;div class=&quot;row&quot;&gt;
      &lt;div class=&quot;col-5 text&quot;&gt;Text 1&lt;/div&gt;
      &lt;div class=&quot;col-2&quot;&gt;&lt;/div&gt;
      &lt;div class=&quot;col-5 text&quot;&gt;Text 1&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;case&quot;&gt;
    &lt;div class=&quot;row&quot;&gt;
      &lt;div class=&quot;col-5 text&quot;&gt;Text 2&lt;/div&gt;
      &lt;div class=&quot;col-2&quot;&gt;&lt;/div&gt;
      &lt;div class=&quot;col-5 text&quot;&gt;Text 2&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;case&quot;&gt;
    &lt;div class=&quot;row&quot;&gt;
      &lt;div class=&quot;col-5 text&quot;&gt;Text 3&lt;/div&gt;
      &lt;div class=&quot;col-2&quot;&gt;&lt;/div&gt;
      &lt;div class=&quot;col-5 text&quot;&gt;Text 3&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;block3&quot;&gt;&lt;/div&gt;

<!-- end snippet -->

答案1

得分: 1

如果我理解你的问题正确的话,我认为你可以将最后一个案例的一半高度添加到maxTop的计算中,像这样:

  let {
    height: lastCaseHeight
  } = cases[cases.length - 1].getBoundingClientRect();
  maxTop = maxTop + (lastCaseHeight / 2)

这样,圆圈的最大顶部位置将位于最后一个案例的中间。请检查更新后的代码片段:

英文:

If i'm understanding your problem correctly, I think you could just add the half height of the last case to the maxTop calculation like this:

  let {
    height: lastCaseHeight
  } = cases[cases.length - 1].getBoundingClientRect();
  maxTop = maxTop + (lastCaseHeight / 2)

This way the maximum top position for the circle will be at the middle of the last case. Please check the updated snippet:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const circle = document.querySelector(&quot;.circle&quot;);
const cases = document.querySelectorAll(&quot;.case&quot;);
let timer = null;

const detectCase = () =&gt; {
  const circleCenter = circle.offsetTop + circle.offsetHeight / 2;
  let activeCase = null,
    minDist = Infinity;
  cases.forEach((elem) =&gt; {
    const caseCenter = elem.offsetTop + elem.offsetHeight / 2;
    const dist = Math.abs(caseCenter - circleCenter);
    if (dist &lt; minDist) {
      minDist = dist;
      activeCase = elem;
    }
  });
  return activeCase;
};

const handleScroll = () =&gt; {
  const {
    height: blockHeight
  } = document.querySelector(&quot;.block2&quot;).getBoundingClientRect();
  let maxTop = cases[cases.length - 1].offsetTop;
  const minTop = cases[0].offsetTop;
  let {
    height: startTop
  } = cases[0].getBoundingClientRect();
  
  let {
    height: lastCaseHeight
  } = cases[cases.length - 1].getBoundingClientRect();
  maxTop = maxTop + (lastCaseHeight / 2)
  
  let scrollDist = startTop / 2 + window.scrollY;
  scrollDist = scrollDist &gt; maxTop ? maxTop : scrollDist &lt; 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(() =&gt; {
    const active = detectCase();
    const activePos = active.offsetTop + active.offsetHeight / 2;
    circle.style.top = `${activePos}px`;
    circle.style.backgroundPosition = `0 ${-activePos}px`;
    circle.style.transition = &quot;0.5s&quot;;
    timer = null;
  }, 800);
  circle.style.transition = &quot;&quot;;
};

const handleWindowSize = () =&gt; {
  if (window.innerWidth &gt;= 991) {
    window.addEventListener(&quot;scroll&quot;, handleScroll);
    window.addEventListener(&quot;resize&quot;, handleScroll);
  } else {
    window.removeEventListener(&quot;scroll&quot;, handleScroll);
    window.removeEventListener(&quot;resize&quot;, handleScroll);
  }
};

handleScroll();
handleWindowSize();
window.addEventListener(&quot;resize&quot;, handleWindowSize);

<!-- language: lang-css -->

.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: &quot;&quot;;
  inset: 3px;
  background-color: white;
}

.text {
  text-align: center;
  padding: 200px 50px;
}

<!-- language: lang-html -->

&lt;link rel=&quot;stylesheet&quot; href=&quot;https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css&quot; integrity=&quot;sha512-t4GWSVZO1eC8BM339Xd7Uphw5s17a86tIZIj8qRxhnKub6WoyhnrxeCIMeAqBPgdZGlCcG2PrZjMc+Wr78+5Xg==&quot; crossorigin=&quot;anonymous&quot; referrerpolicy=&quot;no-referrer&quot;
/&gt;
&lt;div class=&quot;block1&quot;&gt;&lt;/div&gt;
&lt;div class=&quot;block2&quot;&gt;
  &lt;div class=&quot;circle&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;case&quot;&gt;
    &lt;div class=&quot;row&quot;&gt;
      &lt;div class=&quot;col-5 text&quot;&gt;Text 1&lt;/div&gt;
      &lt;div class=&quot;col-2&quot;&gt;&lt;/div&gt;
      &lt;div class=&quot;col-5 text&quot;&gt;Text 1&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;case&quot;&gt;
    &lt;div class=&quot;row&quot;&gt;
      &lt;div class=&quot;col-5 text&quot;&gt;Text 2&lt;/div&gt;
      &lt;div class=&quot;col-2&quot;&gt;&lt;/div&gt;
      &lt;div class=&quot;col-5 text&quot;&gt;Text 2&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;case&quot;&gt;
    &lt;div class=&quot;row&quot;&gt;
      &lt;div class=&quot;col-5 text&quot;&gt;Text 3&lt;/div&gt;
      &lt;div class=&quot;col-2&quot;&gt;&lt;/div&gt;
      &lt;div class=&quot;col-5 text&quot;&gt;Text 3&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;block3&quot;&gt;&lt;/div&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年6月26日 22:29:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76557646.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定