如何根据滚动进度为文本添加动画

问题描述 投票:0回答:1

以下场景:用户正在页面上滚动内容,突然一个元素出现在视口中,其子元素从不同方向飞入屏幕。

一旦元素出现,其子元素就会通过动画在视口中可见,并在离开视口时再次完美消失。文本可能比视口本身大。

各个起始方向可以作为各个元素的属性找到。由于某些事件,位置计算不正确。似乎在正方形的高度和纬度上一切正常。请参阅我在 javascript 代码中的注释。我实际上现在不知道出了什么问题。

请参阅我的小提琴示例代码:https://jsfiddle.net/oqe145tv/23/

那里使用了 jQuery:https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js

<div class="marquee">
  <div class="marquee-row" data-position="start">
    <div class="marquee-row-data">
      <p class="marquee-row-data-text"><span>Mertingen</span></p>
    </div>
    <div class="marquee-row-data">
      <p class="marquee-row-data-text"><span>Praha</span></p>
    </div>
    <div class="marquee-row-data">
      <p class="marquee-row-data-text"><span>Budapest</span></p>
    </div>
    <div class="marquee-row-data">
      <p class="marquee-row-data-text"><span>Bratislava</span></p>
    </div>
    <div class="marquee-row-data">
      <p class="marquee-row-data-text"><span>Das ist ein cooler und langer Test</span></p>
    </div>
  </div>
  <div class="marquee-row" data-position="end">
    <div class="marquee-row-data">
      <p class="marquee-row-data-text"><span>Günzburg</span></p>
    </div>
    <div class="marquee-row-data">
      <p class="marquee-row-data-text"><span>Wroclaw</span></p>
    </div>
    <div class="marquee-row-data">
      <p class="marquee-row-data-text"><span>Opole</span></p>
    </div>
    <div class="marquee-row-data">
      <p class="marquee-row-data-text"><span>Hanoi</span></p>
    </div>
  </div>
</div>
body {
  padding: 30rem 0;
}

.marquee {
  overflow: hidden;
  background-color: green;
}

.marquee-row {
  position: relative;
  display: flex;
  width: fit-content;
}

.marquee-row[data-position="end"] {
  float: right;
}

.marquee-row-data {
  display: flex;
  overflow: hidden;
  padding: 0.5rem 0;
  position: relative;
}

.marquee-row-data:not(:last-child)::after {
  content: '/';
  color: black;
  padding: 0 0.5rem;
}

.marquee-row-data::after,
.marquee-row-data-text>* {
  font-size: 4.5rem;
  line-height: 5rem;
  font-weight: 600;
}

.marquee-row-data-text {
  position: relative;
  white-space: nowrap;
  overflow-x: clip;
}

.marquee-row-data-text span {
  color: black;
  cursor: default;
}

.marquee-row-data-text a {
  color: red;
}
function run() {
  const marquees = $('.marquee');
  if (marquees.length === 0) return;

  const handleSliding = _ => {
    $(marquees).each((_, marquee) => {
      const rows = $(marquee).find('.marquee-row');
      if (rows.length === 0) return;

      const handler = entries => {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            $(window).on('scroll.marquee', _ => {
              $(rows).each((i, row) => {
                const position = $(row).attr('data-position');
                if (!position) return;

                const elementPositionY = row.getBoundingClientRect().top;
                const percentHeight = 100 / window.innerHeight * elementPositionY;
                const startPos = 100 / window.innerWidth * $(row).innerWidth() * -1;

                // percentHeight = percentHeight < 0 ? 0 : percentHeight > 100 ? 100 : percentHeight;
                // fullWidth / window.innerHeight;
                // 100 / (fullWidth / (100 / window.innerHeight * elementPositionY));
                // 100 / ((fullWidth / 100) * (100 / window.innerHeight * elementPositionY));
                // fullWidth / (window.innerHeight + $(marquee).outerHeight())
                const fullWidth = window.innerWidth + $(row).innerWidth();
                const percentWidth = fullWidth / window.innerHeight;


                const percent = startPos + (percentWidth * percentHeight);
                $(row).css(position === 'start' ? 'left' : 'right', `${percent}vw`);
              });
            }).scroll();
          } else
            $(window).off('scroll.marquee');
        });
      };

      const observer = new IntersectionObserver(handler);
      observer.observe(marquee);
    });
  };

  handleSliding();
}

run();
javascript css algorithm math browser
1个回答
0
投票

重写完整的代码后,我设法修复它,如下所示:

const run = _ => {
    const wrappers = document.querySelectorAll('.wrapper');
    if (wrappers.length === 0) return;

    document.addEventListener('scroll', _ => {
        wrappers.forEach(wrapper => {
            const items = wrapper.querySelectorAll('.item');
            if (items.length === 0) return;

            items.forEach((item, i) => {
                if (wrapper.offsetTop > window.scrollY + window.innerHeight || wrapper.offsetTop + wrapper.offsetHeight < window.scrollY) return;

                const position = item.getAttribute('data-position');
                if (!position) return;

                const faktor = 100 / window.innerWidth * ((window.innerWidth + item.offsetWidth) / 100);
                const screenHeight = window.innerHeight - item.offsetHeight;

                let scrollProgress = 100 - (100 / screenHeight * (item.offsetTop - window.scrollY));

                if (scrollProgress > 100) scrollProgress = 100;
                if (scrollProgress < 0) scrollProgress = 0;

                let startPos = 100 - 100 * faktor;

                if (position === 'right')
                    startPos = 100 * faktor - (100 + (100 * faktor));

                const progress = startPos + scrollProgress * faktor;
                item.style = `${position}: ${progress}vw`;
            });
        });
    });
};

run();
body {
    padding: 1500px 0;
    background: #222;
}

.wrapper {
    background: orange;
    overflow: hidden;
    padding: 200px 0;
}

.item {
    background: green;
    height: 100px;
    position: relative;
}

.item:nth-child(1) {
    width: 500px;
}

.item:nth-child(2) {
    width: 2500px;
}

.item:nth-child(3) {
    width: 1000px;
}

.item:nth-child(4) {
    width: 750px;
}

.item:nth-child(5) {
    width: 1800px;
}

.item:nth-child(6) {
    width: 900px;
}
<div class="wrapper">
    <div class="item" data-position="left"></div>
    <div class="item" data-position="right"></div>
    <div class="item" data-position="left"></div>
    <div class="item" data-position="left"></div>
    <div class="item" data-position="right"></div>
    <div class="item" data-position="right"></div>
</div>

© www.soinside.com 2019 - 2024. All rights reserved.