使用交叉观察器在用户滚动时旋转图像

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

我刚刚在这个网站上看到了一个精彩的滚动动画https://thehungryfamily.com/bon-bouquet-cafe/。 当用户滚动时,一些图标会不断旋转。我尝试模仿相同的动画,但无法理解其中的逻辑。

到目前为止我做了什么

  • 使用交集观察器来检测视口中的图标/图像容器
  • 使用交集观察器boundingClientRect.y来检测用户是否从上到下或从下到上滚动以更改旋转行为
  • 在数组中添加相交观察者阈值的值,以便它不断触发观察者回调

但不知何故我仍然错过了一些逻辑。我面临的挑战是确定用户滚动方向(用户是从上到下还是从下到上滚动)

这是我的代码

function getAngle(str)
{
  if(str)
  {
    let angle=str.split("(");
    let angleArr=angle[1].split("t");
    return parseFloat(angleArr[0]);
  }
}

const globeOptions = {
  rootMargin: '0px',
  threshold: [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1]
}
const globeCallback = entries => {
    entries.forEach(entry => {
        const currentY = entry.boundingClientRect.y
        const currentRatio = entry.intersectionRatio
        const isIntersecting = entry.isIntersecting;
        let prevAngle=
        entry.target.style.transform ? getAngle(entry.target.style.transform):0;
    
        if (currentY < previousY) {
          if (currentRatio > previousRatio && isIntersecting) {
            entry.target.style.transform=`rotate(${prevAngle+0.2}turn)`;
          } else {
            entry.target.style.transform=`rotate(${prevAngle+0.2}turn)`;
          }
        } else if (currentY > previousY && isIntersecting) {
          if (currentRatio < previousRatio) {
            entry.target.style.transform=`rotate(${-(prevAngle-0.2)}turn)`;
          } else {
            entry.target.style.transform=`rotate(${-(prevAngle-0.2)}turn)`;
          }
        }
    
        previousY = currentY
        previousRatio = currentRatio
    })
  }

const globeobserver = new IntersectionObserver(globeCallback, globeOptions)


const globeTarget = document.querySelector('.globe-box img')
globeobserver.observe(globeTarget)

javascript html css
1个回答
0
投票

我只会监听主监听器上的滚动事件并根据此信息计算旋转。 如果要保证每个元素的初始显示,计算可能会稍微复杂一些,但这种方法仍然有效。

const container = document.querySelector('.container')
const main = document.querySelector('.main')

function handleScroll () {
  const icons = document.querySelectorAll('.icon')
  const rotate = container.scrollTop / 10
  icons.forEach((icon, index) => {
    icon.style.transform = `rotate(${index % 2 === 0 ? '' : '-'}${rotate}deg)`
  })
}
container.addEventListener('scroll', handleScroll)
body {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  overflow: hidden;
}
.container {
  height: 100%;
  width: 100%;
  overflow: auto;
}
.main {
  height: 2000px;
  width: 100%;
}
.icon {
  margin: 10px;
  display: inline-block;
  height: 30px;
  width: 30px;
  transition: transform 0.15s;
}
.icon:nth-child(odd) {
  background-image: url(https://thehungryfamily.com/storage/2024/07/BBV-illustration-elements-11.svg);
  background-repeat: no-repeat;
}
.icon:nth-child(even) {

  background-image: url(https://thehungryfamily.com/storage/2024/07/BBV-illustration-elements-10.svg);
  background-repeat: no-repeat;
}
<div class='container'>
  <div class='main'>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
        <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
    <div class='icon'></div>
  </div>
</div>

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