Animate text as the user scrolls over a sticky positioned div

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

Animate text as the user scrolls over a sticky positioned div

问题

我正在尝试在用户滚动时动画显示四个标题。首先,我创建一个sticky定位的div,然后用户滚动到标题上,依次切换类.active,最后一个保持可见,继续滚动到最后一个div。

我的问题是,一旦.sticky div变为粘性,浏览器就不再检测进一步的滚动,直到div再次变为非粘性。

--- 更新

我已经更改了代码以按顺序过渡,效果更好,但我想在.sticky div变为粘性时才开始动画,但我尝试过,滚动动画完全停止工作。另外,我想将所有标题保持在同一个块中,但如果我在它们上面使用position: absolute,动画也会出问题。

const headings = Array.from(document.querySelectorAll('.animated-text'));
const sticky = document.querySelector('.sticky');

let currentActive = null;

window.addEventListener('scroll', () => {
  const viewportHeight = window.innerHeight;
  headings.forEach((heading, index) => {
    const headingRect = heading.getBoundingClientRect();

    if (headingRect.top <= viewportHeight / 2) {
      if (currentActive) {
        currentActive.classList.remove('active');
      }
      heading.classList.add('active');
      currentActive = heading;
    }
  });
});
body {
  margin: 0;
}

section {
  position: relative;
}

.sticky {
  padding-bottom: 150px;
  background: #2d232c;
  position: sticky;
  top: 0;
  overflow: hidden;
  height: auto;
  color: white;
}

.animated-text {
  opacity: 0;
  height: 0;
  overflow: hidden;
  transition: opacity 1s ease, height 1s ease, transform 1s ease;
  transform: translateY(0);
}

.animated-text.active {
  height: auto;
  opacity: 1;
  transform: translateY(-20px);
}

.hero,
.end {
  height: 100px;
  background: white;
}
<section class='hero'>
  <p>Start</p>
</section>

<section class='sticky'>
  <div class='text-animations'>
    <h1 class='animated-text active'>Intro</h1>
    <h2 class='animated-text'>First</h2>
    <h2 class='animated-text'>Second</h2>
    <h2 class='animated-text'>Third</h2>
  </div>
  <p class='intro_content'>
     Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam
  </p>  
</section>

<section class='end'>
  <p>End<p>
</section>

希望这有所帮助!如果您有其他问题,请随时提问。

英文:

I am trying to animate four headings as the user scrolls. First I create a sticky positioned div, then the user scrolls over the headings toggling the class .active one at a time, leaving the last one visible and continuing scrolling to the last div.

The problem I am having is that once the .sticky div becomes sticky the browser no longer detects further scrolling until the div becomes non-sticky again.

--- UPDATE

I have changed the code to transition sequentially and works better, but I would like to start the animations only when the .sticky div becomes sticky, but I tried that and the scroll animation stops working completely. Also, I would like to keep all headings on the same block but If I do position: absolute on them it breaks the animations too.

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

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

const headings = Array.from(document.querySelectorAll(&#39;.animated-text&#39;));
const sticky = document.querySelector(&#39;.sticky&#39;);

let currentActive = null;

window.addEventListener(&#39;scroll&#39;, () =&gt; {
  const viewportHeight = window.innerHeight;
  headings.forEach((heading, index) =&gt; {
    const headingRect = heading.getBoundingClientRect();

    if (headingRect.top &lt;= viewportHeight / 2) {
      if (currentActive) {
        currentActive.classList.remove(&#39;active&#39;);
      }
      heading.classList.add(&#39;active&#39;);
      currentActive = heading;
    }
  });
});

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

body {
  margin: 0
}

section {
  position: relative;
}

.sticky {
  padding-bottom: 150px;
  background: #2d232c;
  position: sticky;
  top: 0;
  overflow: hidden;
  height: auto;
  color: white;
}

.animated-text {
  opacity: 0;
  height: 0;
  overflow: hidden;
  transition: opacity 1s ease, height 1s ease, transform 1s ease;
  transform: translateY(0);
}

.animated-text.active {
  height: auto;
  opacity: 1;
  transform: translateY(-20px);
}

.hero, .end {
  height: 100px;
  background: white;
}

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

&lt;section class=&#39;hero&#39;&gt;
  &lt;p&gt;Start&lt;/p&gt;
&lt;/section&gt;

&lt;section class=&#39;sticky&#39;&gt;
  &lt;div class=&#39;text-animations&#39;&gt;
    &lt;h1 class=&#39;animated-text active&#39;&gt;Intro&lt;/h1&gt;
    &lt;h2 class=&#39;animated-text&#39;&gt;First&lt;/h2&gt;
    &lt;h2 class=&#39;animated-text&#39;&gt;Second&lt;/h2&gt;
    &lt;h2 class=&#39;animated-text&#39;&gt;Third&lt;/h2&gt;
  &lt;/div&gt;
  &lt;p class=&#39;intro_content&#39;&gt;
     Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam
  &lt;/p&gt;  
&lt;/section&gt;

&lt;section class=&#39;end&#39;&gt;
  &lt;p&gt;End&lt;p&gt;
&lt;/section&gt;

<!-- end snippet -->

答案1

得分: 0

看起来你正在尝试在用户滚动并粘性 div 进入视图时为标题创建动画效果。然而,当前的代码只处理滚动事件一次,并且在 .sticky div 变为粘性后滚动不会继续。

为了实现期望的效果,即在用户滚动时逐个切换标题的 "active" 类,你需要不断检查滚动位置并相应地更新活动标题。你可以使用 getBoundingClientRect() 方法来确定标题相对于视口的位置。

const headings = document.querySelectorAll('.animated-text');
const sticky = document.querySelector('.sticky');

window.addEventListener('scroll', () => {
  const stickyRect = sticky.getBoundingClientRect();

  headings.forEach((heading, index) => {
    const headingRect = heading.getBoundingClientRect();

    // Check if the heading is inside the sticky div and has come into view
    if (headingRect.top >= stickyRect.top && headingRect.bottom <= stickyRect.bottom) {
      // Add 'active' class to the current heading and remove it from the others
      heading.classList.add('active');
      for (let i = 0; i < headings.length; i++) {
        if (i !== index) {
          headings[i].classList.remove('active');
        }
      }
    }
  });
});

通过这个更新后的代码,当用户滚动并 .sticky div 变为粘性时,浏览器将继续检测进一步的滚动,并相应地更新标题的 "active" 类,提供所需的逐个标题动画效果。

英文:

It looks like you are trying to create an animation effect for your headings as the user scrolls and the sticky div comes into view. However, the current code only handles the scroll event once, and the scrolling doesn't continue after the .sticky div becomes sticky.

To achieve the desired effect of toggling the "active" class for the headings one by one as the user scrolls, you'll need to continuously check the scroll position and update the active heading accordingly. You can achieve this by using the getBoundingClientRect() method to determine the positions of the headings relative to the viewport.

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

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

const headings = document.querySelectorAll(&#39;.animated-text&#39;);
const sticky = document.querySelector(&#39;.sticky&#39;);

window.addEventListener(&#39;scroll&#39;, () =&gt; {
  const stickyRect = sticky.getBoundingClientRect();

  headings.forEach((heading, index) =&gt; {
    const headingRect = heading.getBoundingClientRect();

    // Check if the heading is inside the sticky div and has come into view
    if (headingRect.top &gt;= stickyRect.top &amp;&amp; headingRect.bottom &lt;= stickyRect.bottom) {
      // Add &#39;active&#39; class to the current heading and remove it from the others
      heading.classList.add(&#39;active&#39;);
      for (let i = 0; i &lt; headings.length; i++) {
        if (i !== index) {
          headings[i].classList.remove(&#39;active&#39;);
        }
      }
    }
  });
});

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

body {
  margin: 0;
}
section {
  position: relative;
}
.sticky {
  padding-bottom: 150px;
  background: #2d232c;
  position: sticky;
  top: 0;
  overflow: hidden;
  height: auto;
  color: white;
}
.animated-text {
  opacity: 0;
  max-height: 0;
  transition: opacity 1s ease, max-height 1s ease;
}
.animated-text.active {
  max-height: 1000px;
  opacity: 1;   
}
.hero, .end {
  height: 100px;
  background: white;
}

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

&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;title&gt;Scroll Animation&lt;/title&gt;
 
&lt;/head&gt;
&lt;body&gt;
  &lt;section class=&#39;hero&#39;&gt;
    &lt;p&gt;Hero space&lt;/p&gt;
  &lt;/section&gt;

  &lt;section class=&#39;sticky&#39;&gt;
    &lt;div class=&#39;text-animations&#39;&gt;
      &lt;h1 class=&#39;animated-text active&#39;&gt;Intro&lt;/h1&gt;
      &lt;h2 class=&#39;h1 animated-text&#39;&gt;First&lt;/h2&gt;
      &lt;h2 class=&#39;h1 animated-text&#39;&gt;Second&lt;/h2&gt;
      &lt;h2 class=&#39;h1 animated-text&#39;&gt;Third&lt;/h2&gt;
      &lt;h3 class=&#39;intro_content&#39;&gt;
        Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam
      &lt;/h3&gt;
    &lt;/div&gt;      
  &lt;/section&gt;

  &lt;section class=&#39;end&#39;&gt;
    &lt;p&gt;Ends&lt;p&gt;
  &lt;/section&gt;

<!-- end snippet -->

With this updated code, as the user scrolls and the .sticky div becomes sticky, the browser will continue to detect further scrolling and update the "active" class for the headings accordingly, providing the desired animation effect for the headings one by one.

答案2

得分: 0

根据要求,要将所有标题定位到顶部,可以在.active类中添加以下样式解决问题:

position: absolute;
top: 0;

而要在div变为粘性(sticky)时才开始动画,需要比较粘性元素的位置,然后实现动画逻辑。

我尝试过根据滚动事件的上下滚动来切换标题的过渡效果,以确保标题在滚动方向无关的情况下正确过渡。我知道代码需要进行大量重构,但希望它能按照要求工作。

以下是代码示例:

let headings = Array.from(document.querySelectorAll('.animated-text'));
const sticky = document.querySelector('.sticky');
let lastScrollTop = 0;
let currentActive = 0;
window.addEventListener('scroll', () => {
  const stickyDiv = sticky.getBoundingClientRect();
  let st = window.pageYOffset || document.documentElement.scrollTop;
  if (st > lastScrollTop) {
    if (stickyDiv.top === 0) {
      for (let i = currentActive; i < headings.length - 1; i++) {
        const headingRect = headings[i].getBoundingClientRect();
        if (headingRect.top <= 0) {
          currentActive = i + 1;
          headings[i].classList.remove('active');
          headings[i + 1].classList.add('active');
        }
      }
    }
  } else if (st < lastScrollTop) {
    if (stickyDiv.top === 0) {
      for (let i = currentActive; i > 0; i--) {
        const headingRect = headings[i].getBoundingClientRect();
        if (headingRect.top <= 0) {
          currentActive = i - 1;
          headings[i].classList.remove('active');
          headings[i - 1].classList.add('active');
        }
      }
    }
  }
  if (stickyDiv.top > 0) {
    headings[currentActive].classList.remove('active');
    currentActive = 0;
    headings[0].classList.add('active');
  }
  lastScrollTop = st <= 0 ? 0 : st;
});

希望这可以帮助您满足要求。如果有任何不清楚的逻辑部分或需要澄清的地方,请随时提问。

英文:

As per the requirementm for positioning all headings at the top, adding

position:absolute; 
top:0;

in .active class resolves the problem.

And for starting animation only when the div becomes sticky, the stickyDiv position needs to be compared and then the animation logic should be implemented.

I have tried to put the logic for transitioning of headings on the basis of scroll up or down event too so that the heading transition correctly in order irrespective of scroll direction.
I am aware the code requires a lot of refactoring, but I hope it works as per the requirement.

let headings = Array.from(document.querySelectorAll(&#39;.animated-text&#39;));
const sticky = document.querySelector(&#39;.sticky&#39;);
let lastScrollTop = 0;
let currentActive=0;
window.addEventListener(&#39;scroll&#39;, () =&gt; {
const stickyDiv=sticky.getBoundingClientRect(); 
let st = window.pageYOffset || document.documentElement.scrollTop; 
if (st &gt; lastScrollTop) {
if (stickyDiv.top===0) {
for(let i=currentActive;i&lt;headings.length-1;i++)
{
const headingRect = headings[i].getBoundingClientRect();
if(headingRect.top&lt;=0){
currentActive=i+1;
headings[i].classList.remove(&#39;active&#39;);
headings[i+1].classList.add(&#39;active&#39;);
}
}
}
} else if (st &lt; lastScrollTop) {
if (stickyDiv.top===0) {
for(let i=currentActive;i&gt;0;i--)
{
const headingRect = headings[i].getBoundingClientRect();
if(headingRect.top&lt;=0){
currentActive=i-1;
headings[i].classList.remove(&#39;active&#39;);
headings[i-1].classList.add(&#39;active&#39;);
}
}
} }
if(stickyDiv.top&gt;0){
headings[currentActive].classList.remove(&#39;active&#39;);
currentActive=0;
headings[0].classList.add(&#39;active&#39;);
}
lastScrollTop = st &lt;= 0 ? 0 : st; 
});

The full code snippet is as follows:-

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

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

let headings = Array.from(document.querySelectorAll(&#39;.animated-text&#39;));
const sticky = document.querySelector(&#39;.sticky&#39;);
let lastScrollTop = 0;
let currentActive=0;
window.addEventListener(&#39;scroll&#39;, () =&gt; {
const stickyDiv=sticky.getBoundingClientRect(); 
let st = window.pageYOffset || document.documentElement.scrollTop; 
if (st &gt; lastScrollTop) {
if (stickyDiv.top===0) {
for(let i=currentActive;i&lt;headings.length-1;i++)
{
const headingRect = headings[i].getBoundingClientRect();
if(headingRect.top&lt;=0){
currentActive=i+1;
headings[i].classList.remove(&#39;active&#39;);
headings[i+1].classList.add(&#39;active&#39;);
}
}
}
} else if (st &lt; lastScrollTop) {
if (stickyDiv.top===0) {
for(let i=currentActive;i&gt;0;i--)
{
const headingRect = headings[i].getBoundingClientRect();
if(headingRect.top&lt;=0){
currentActive=i-1;
headings[i].classList.remove(&#39;active&#39;);
headings[i-1].classList.add(&#39;active&#39;);
}
}
} }
if(stickyDiv.top&gt;0){
headings[currentActive].classList.remove(&#39;active&#39;);
currentActive=0;
headings[0].classList.add(&#39;active&#39;);
}
lastScrollTop = st &lt;= 0 ? 0 : st; 

});

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

body {
margin: 0
}
section {
position: relative;
}
.sticky {
padding-bottom: 150px;
background: #2d232c;
position: sticky;
top: 0;
overflow: hidden;
height: auto;
color: white;
}
.animated-text {
opacity: 0;
height: 0;
overflow: hidden;
transition: opacity 1s ease, height 1s ease, transform 1s ease;
transform: translateY(0);
}
.animated-text.active {
position:absolute;
top:0;
height: auto;
opacity: 1;
transform: translateY(-20px);
}
.hero, .end {
height: 100px;
background: white;
}

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

&lt;section class=&#39;hero&#39;&gt;
  &lt;p&gt;Start&lt;/p&gt;
&lt;/section&gt;

&lt;section class=&#39;sticky&#39;&gt;
  &lt;div class=&#39;text-animations&#39;&gt;
    &lt;h1 class=&#39;animated-text active&#39;&gt;Intro&lt;/h1&gt;
    &lt;h2 class=&#39;animated-text&#39;&gt;First&lt;/h2&gt;
    &lt;h2 class=&#39;animated-text&#39;&gt;Second&lt;/h2&gt;
    &lt;h2 class=&#39;animated-text&#39;&gt;Third&lt;/h2&gt;
  &lt;/div&gt;
  &lt;p class=&#39;intro_content&#39;&gt;
     Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam
  &lt;/p&gt;  
&lt;/section&gt;

&lt;section class=&#39;end&#39;&gt;
  &lt;p&gt;End&lt;p&gt;
&lt;/section&gt;

<!-- end snippet -->

Please feel free to ask if any part of the logic is unclear or require clarification.

答案3

得分: 0

我最终选择了更好的滚动时使用translateY方法

const items = $('.animated-text')
const carousel = $('.sticky')
const windowHeight = $(window).height()

// 为每个轮播项设置原始的data-offset值。
items.each(function (i) {
  $(this).attr('data-offset', windowHeight * i)
})

$(window).scroll(function () {
  const scrollTop = $(window).scrollTop()
  const carouselTop = carousel.offset().top
  const carouselBottom = carouselTop + carousel.height()

  items.each(function () {
    const itemIndex = $(this).index()
    const itemOffset = parseInt($(this).attr('data-offset'), 10)
    const nextItemOffset = items.eq(itemIndex + 1).attr('data-offset')
    const offsetRatio = (scrollTop - itemOffset) / windowHeight

    // 根据滚动位置计算不透明度和变换值。
    let opacity = 1 - Math.abs(offsetRatio * 2)

    const translateY = -offsetRatio * 100

    // 只有在轮播可见时应用样式。
    if (scrollTop >= carouselTop && scrollTop < carouselBottom) {
      $(this).css({
        opacity: opacity,
        transform: `translateY(${translateY}%)`
      })

      // 检查下一个项是否可见,如果是,隐藏当前项。
      if (nextItemOffset && scrollTop >= nextItemOffset) {
        $(this).css({ opacity: 0 })
      }
    } else if (scrollTop < carouselTop) {
      // 当滚动在轮播上方时,重置所有项的变换
      // 但只保留第一个项目可见。
      if ($(this).index() === 0) {
        $(this).css({
          opacity: 1,
          transform: 'translateY(0%)'
        })
      } else {
        $(this).css({
          opacity: 0,
          transform: 'translateY(0%)'
        })
      }
    }
  })
})
body {
  margin: 0
}

section {
  position: relative;
}

.sticky {
  height: 400vh;
}

.sticky__inner {
  background: #2d232c;
  overflow: hidden;
  align-items: center;
  color:#fff;
  display:flex;
  height: 100vh;
  justify-content:center;
  perspective:70rem;
  position:sticky;
  top: 0;
}

.text-animations {
  height: 60vh;
  position: relative;
  transform-origin: 50% 50%;
  transform-style: preserve-3d;
  width: 100vw;
  margin-top: -200px;
  left: 70px;
}

.animated-text {
  margin-top: 10vh; /* 需要时调整此值 */
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  
  position: absolute;
  transform-origin: 50% 50%;
  transition: all 0.5s ease-in-out; /* 添加这行 */
  opacity: 0;

}

.animated-text :first-of-type {
  opacity: 1;
}

.hero, .end {
  height: 100px;
  background: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<section class='hero'>
  <p>开始</p>
</section>

<section class='sticky'>
 <div class='sticky__inner'>
  <div class='text-animations'>
    <h1 class='animated-text active'>介绍</h1>
    <h2 class='animated-text'>第一</h2>
    <h2 class='animated-text'>第二</h2>
    <h2 class='animated-text'>第三</h2>
  </div>

  <p class='intro_content'>
     Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam
  </p>  
  </div>
</section>

<section class='end'>
  <p>结束</p>
</section>
英文:

I am ended up using the translateY on scroll method better

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

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

const items = $(&#39;.animated-text&#39;)
const carousel = $(&#39;.sticky&#39;)
const windowHeight = $(window).height()
// Set the original data-offset value for each carousel item.
items.each(function (i) {
$(this).attr(&#39;data-offset&#39;, windowHeight * i)
})
$(window).scroll(function () {
const scrollTop = $(window).scrollTop()
const carouselTop = carousel.offset().top
const carouselBottom = carouselTop + carousel.height()
items.each(function () {
const itemIndex = $(this).index()
const itemOffset = parseInt($(this).attr(&#39;data-offset&#39;), 10)
const nextItemOffset = items.eq(itemIndex + 1).attr(&#39;data-offset&#39;)
const offsetRatio = (scrollTop - itemOffset) / windowHeight
// Calculate opacity and transform values based on the scroll position.
let opacity = 1 - Math.abs(offsetRatio * 2)
const translateY = -offsetRatio * 100
// Only apply styles when the carousel is visible.
if (scrollTop &gt;= carouselTop &amp;&amp; scrollTop &lt; carouselBottom) {
$(this).css({
opacity: opacity,
transform: `translateY(${translateY}%)`
})
// Check if the next item is visible, if so, hide the current item.
if (nextItemOffset &amp;&amp; scrollTop &gt;= nextItemOffset) {
$(this).css({ opacity: 0 })
}
} else if (scrollTop &lt; carouselTop) {
// When scrolling is above the carousel, reset the transformation for all items
// But keep only the first item visible
if ($(this).index() === 0) {
$(this).css({
opacity: 1,
transform: &#39;translateY(0%)&#39;
})
} else {
$(this).css({
opacity: 0,
transform: &#39;translateY(0%)&#39;
})
}
}
})
})

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

body {
margin: 0
}
section {
position: relative;
}
.sticky {
height: 400vh;
}
.sticky__inner {
background: #2d232c;
overflow: hidden;
align-items: center;
color:#fff;
display:flex;
height: 100vh;
justify-content:center;
perspective:70rem;
position:sticky;
top: 0;
}
.text-animations {
height: 60vh;
position: relative;
transform-origin: 50% 50%;
transform-style: preserve-3d;
width: 100vw;
margin-top: -200px;
left: 70px;
}
.animated-text {
margin-top: 10vh; /* adjust this value as needed */
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
position: absolute;
transform-origin: 50% 50%;
transition: all 0.5s ease-in-out; /* Add this line */
opacity: 0;
}
.animated-text :first-of-type {
opacity: 1;
}
.hero, .end {
height: 100px;
background: white;
}

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

&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;section class=&#39;hero&#39;&gt;
&lt;p&gt;Start&lt;/p&gt;
&lt;/section&gt;
&lt;section class=&#39;sticky&#39;&gt;
&lt;div class=&#39;sticky__inner&#39;&gt;
&lt;div class=&#39;text-animations&#39;&gt;
&lt;h1 class=&#39;animated-text active&#39;&gt;Intro&lt;/h1&gt;
&lt;h2 class=&#39;animated-text&#39;&gt;First&lt;/h2&gt;
&lt;h2 class=&#39;animated-text&#39;&gt;Second&lt;/h2&gt;
&lt;h2 class=&#39;animated-text&#39;&gt;Third&lt;/h2&gt;
&lt;/div&gt;
&lt;p class=&#39;intro_content&#39;&gt;
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam
&lt;/p&gt;  
&lt;/div&gt;
&lt;/section&gt;
&lt;section class=&#39;end&#39;&gt;
&lt;p&gt;End&lt;p&gt;
&lt;/section&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年7月27日 20:54:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76779949.html
匿名

发表评论

匿名网友

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

确定