根据滚动在页面上移动元素

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

Move element on page based on scroll

问题

在当前页面上,我有3个区块。

在第二个区块上,有3个案例(可能更多),还有一条背景线,并且在该线的中间有一个圆圈。

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

<!-- language: lang-css -->
.block1 {
  height: 200px;
  background-color: gray;
}

.block2 {
  height: 100%;
  background: linear-gradient(214deg, rgba(79, 142, 255, 0.00) 0%, #4F8EFF 10%, #F5E550 90%, rgba(79, 142, 255, 0.00) 100%) center / 3px calc(100% - 100px) no-repeat;
  
  .circle {
    position: relative;
    width: 15px;
    height: 15px;
    background-color: white;
    border: solid 3px #4F8EFF;
    border-radius: 50%;
    top: 50%;
    left: calc(50% - 8px);
  }
}

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

.block3 {
  height: 200px;
  background-color: gray;
}

<!-- language: lang-html -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css" integrity="sha512-t4GWSZ...

<div class="block1"></div>

<div class="block2">
  <div class="case">
    <div class="row">
      <div class="col-5 text">Text 1</div>
      <div class="col-2">
        <div class="circle"></div>
      </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>

<!-- end snippet -->

目前,这个圆圈仅适用于第一个案例,位于 <div class="col-2"> 内。

是否可能使其根据页面滚动在所有案例之间移动,并变为空的 <div class="col-2">,就像我绘制的那样?重要的是,这个圆圈的颜色与线的颜色相同。

也就是说,如果我们在第一个案例的页面中部,那么圆圈应该在该位置,如果我们向下滚动到第二个案例,那么圆圈应该相应地移动到第二个案例,同时我希望圆圈本身随着滚动而滑动,并在滚动停止后移动到最近的案例。

英文:

I have 3 blocks on the page.

On the second block, I have 3 cases (maybe more), there is also a background line, and there is a circle in the middle of the case on this line

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

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

.block1 {
height: 200px;
background-color: gray;
}
.block2 {
height: 100%;
background: linear-gradient(214deg, rgba(79, 142, 255, 0.00) 0%, #4F8EFF 10%, #F5E550 90%, rgba(79, 142, 255, 0.00) 100%) center / 3px calc(100% - 100px) no-repeat;
.circle {
position: relative;
width: 15px;
height: 15px;
background-color: white;
border: solid 3px #4F8EFF;
border-radius: 50%;
top: 50%;
left: calc(50% - 8px);
}
}
.text {
text-align: center;
padding: 200px 50px;
}
.block3 {
height: 200px;
background-color: gray;
}

<!-- 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;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 class=&quot;circle&quot;&gt;&lt;/div&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 -->

Right now this circle is only for the first case, inside &lt;div class=&quot;col-2&quot;&gt;

Is it possible to make it so that, depending on the page scroll, this circle moves through all cases, and becomes empty &lt;div class=&quot;col-2&quot;&gt;, just like I drew. And it is important that the color of this circle is the same as the color of the line

That is, if we are in the middle of the page of the first case, then the circle should be on it, if we moved lower to the second case, then the circle should accordingly move to the second case, while I would like the circle itself to slide along with the scroll, and when scroll stop moved to the nearest case

根据滚动在页面上移动元素

答案1

得分: 1

I moved .circle out of .case so we only need to change its top.

detectCase() will find out which .case is closest to .circle.

handleScroll() will change .circle's top and backgroundPosition so its position and color will change while scrolling.

英文:

I moved .circle out of .case so we only need to change its top.

detectCase() will find out which .case is closest to .circle

handleScroll() will change .circle's top & backgroundPosition so its position and color will change while scroll.

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

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

class ScrollCircle {
constructor(container) {
this.container = container;
this.cases = this.container.querySelectorAll(&quot;.case&quot;);
this.circle = this.container.querySelector(&quot;.circle&quot;);
this.timer = null;
this.lastScrollPosition = window.scrollY;
this.lastCircleTop = null;
this.handleScroll();
this.handleWindowSize();
window.addEventListener(&quot;resize&quot;, this.handleWindowSize);
}
detectCase = () =&gt; {
const circleCenter = this.circle.offsetTop + this.circle.offsetHeight / 2;
let activeCase = null,
minDist = Infinity;
this.cases.forEach((elem) =&gt; {
const caseTop = elem.offsetTop + elem.offsetHeight / 3;
const dist = Math.abs(caseTop - circleCenter);
if (dist &lt; minDist) {
minDist = dist;
activeCase = elem;
}
});
return activeCase;
};
scrollDown = () =&gt; {
let down = window.scrollY &gt; this.lastScrollPosition ? true : false;
this.lastScrollPosition = window.scrollY;
return down;
};
handleScroll = () =&gt; {
const maxTop = this.cases[this.cases.length - 1].offsetTop + this.cases[this.cases.length - 1].offsetHeight / 2;
const minTop = this.cases[0].offsetHeight / 2;
let {
height: startTop
} = this.cases[0].getBoundingClientRect();
let circleTop = startTop / 2 + window.scrollY - this.container.offsetTop;
circleTop = circleTop &gt; maxTop ? maxTop : circleTop &lt; minTop ? minTop : circleTop;
let down = this.scrollDown();
if ((circleTop &lt; this.lastCircleTop &amp;&amp; down) | (circleTop &gt; this.lastCircleTop &amp;&amp; !down)) {
this.circle.style.top = `${this.lastCircleTop}px`;
this.circle.style.backgroundPosition = `0 ${-this.lastCircleTop}px`;
} else {
this.circle.style.top = `${circleTop}px`;
this.circle.style.backgroundPosition = `0 ${-circleTop}px`;
}
this.circle.style.backgroundSize = `15px ${this.container.offsetHeight}px`;
if (this.timer) return;
this.timer = setTimeout(() =&gt; {
const active = this.detectCase();
circleTop = active.offsetTop + active.offsetHeight / 2;
this.circle.style.top = `${circleTop}px`;
this.circle.style.backgroundPosition = `0 ${-circleTop}px`;
this.circle.style.transition = &quot;0.5s&quot;;
this.lastCircleTop = circleTop;
this.timer = null;
}, 800);
this.circle.style.transition = null;
};
handleWindowSize = () =&gt; {
if (window.innerWidth &gt;= 991) {
window.addEventListener(&quot;scroll&quot;, this.handleScroll);
window.addEventListener(&quot;resize&quot;, this.handleScroll);
} else {
window.removeEventListener(&quot;scroll&quot;, this.handleScroll);
window.removeEventListener(&quot;resize&quot;, this.handleScroll);
}
};
}
new ScrollCircle(document.querySelector(&quot;.block2&quot;));

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

.block1,
.block3 {
height: 1000px;
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;
}
/*# sourceMappingURL=so.css.map */

<!-- 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 -->

答案2

得分: 0

以下是您提供的代码的翻译部分:

这应该更像是一个评论而不是答案... 这是我如何与滚动交互的方式,但缺少颜色更改。

哦!你应该给`.col-2`赋予某种ID,以改善圆圈移动的筛选!

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

<!-- language: lang-js -->
$(document).on('scroll', function() {
  const offset = 0;
  let $circle = $('.circle');
  $('.case').each(function() {
    if(window.scrollY > ($(this).offset().top - offset)) {
      $(this).find('.col-2').append($circle);
    }
  });
});

<!-- language: lang-css -->
.block1 {
  height: 200px;
  background-color: gray;
}

.block2 {
  height: 100%;
  background: linear-gradient(214deg, rgba(79, 142, 255, 0.00) 0%, #4F8EFF 10%, #F5E550 90%, rgba(79, 142, 255, 0.00) 100%) center / 3px calc(100% - 100px) no-repeat;
  
  .circle {
    position: relative;
    width: 15px;
    height: 15px;
    background-color: white;
    border: solid 3px #4F8EFF;
    border-radius: 50%;
    top: 50%;
    left: calc(50% - 8px);
  }
}

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

.block3 {
  height: 200px;
  background-color: gray;
}

<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<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="case">
    <div class="row">
      <div class="col-5 text">Text 1</div>
      <div class="col-2">
        <div class="circle"></div>
       </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>

<!-- end snippet -->

请注意,这是您提供的代码的中文翻译部分。

英文:

This should be more a comment then an answer... Here is how I would play with scroll, but color change is missing.

Oh! And you should give to .col-2 some sort of ID to improve filtering on circle movement!

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

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

$(document).on(&#39;scroll&#39;, function() {
const offset = 0;
let $circle = $(&#39;.circle&#39;);
$(&#39;.case&#39;).each(function() {
if(window.scrollY &gt; ($(this).offset().top - offset)) {
$(this).find(&#39;.col-2&#39;).append($circle);
}
});
});

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

.block1 {
height: 200px;
background-color: gray;
}
.block2 {
height: 100%;
background: linear-gradient(214deg, rgba(79, 142, 255, 0.00) 0%, #4F8EFF 10%, #F5E550 90%, rgba(79, 142, 255, 0.00) 100%) center / 3px calc(100% - 100px) no-repeat;
.circle {
position: relative;
width: 15px;
height: 15px;
background-color: white;
border: solid 3px #4F8EFF;
border-radius: 50%;
top: 50%;
left: calc(50% - 8px);
}
}
.text {
text-align: center;
padding: 200px 50px;
}
.block3 {
height: 200px;
background-color: gray;
}

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

&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js&quot;&gt;&lt;/script&gt;
&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;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 class=&quot;circle&quot;&gt;&lt;/div&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月6日 02:58:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76409274.html
匿名

发表评论

匿名网友

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

确定