做完这个,你就知道IntersectionObserver有什么用了。

68 阅读1分钟

前言

先看看我们要整什么

bandicam 2025-04-29 08-44-22-668.gif

这个前进效果看起来挺好,好像挺有意思,F12打开一看,额。。。 image.png
原来轱辘和车是分离的,我们把它的图片download下来
car_drive_whell.png

car_drive.png

开始干活

创建项目

用Vite创建个原生JS项目,为什么用原生JS?问就是没苦硬吃

pnpx create-vite test
# 选择Vanilla + Javascript
cd test
# 安装依赖
pnpm i
# 打开Vscode
code .

image.png

image.png

修改index.html

我们先写好基础的页面结构如下:

  • 页面高度200vh
  • 车子定位到右下角
  • 两个轱辘安排到它应该去的位置

把车和轱辘的图片放到public文件夹下。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite App</title>
    <style>
      .wrap {
        /* 让我们能滚动 */
        height: 200vh;
        position: relative;
        overflow: hidden;
      }
      .inner {
        /* 车定位到右下角 */
        position: absolute;
        bottom: 0;
        right: -500px;
      }
      .car {
        width: 500px;
      }
      /* 轱辘 */
      .wheel {
        position: absolute;
        bottom: 0;
        width: 70px;
      }
      .wheel-front {
        left: 78px;
      }
      .wheel-back {
        right: 103px;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div class="wrap">
        <div class="inner">
          <img src="/car_drive.png" alt="car" class="car" />
          <img src="/car_drive_whell.png" alt="wheel" class="wheel wheel-front" />
          <img src="/car_drive_whell.png" alt="wheel" class="wheel wheel-back" />
        </div>
      </div>
    </div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

修改main.js

先安装个gsap

pnpm i gsap
import gsap from "gsap";
// 获取车和轮子的Dom
const inner = document.querySelector(".inner");
const wheel = document.querySelectorAll(".wheel");

// 让轮子转起来
const wheelAnimation = gsap.to(wheel, {
  rotation: -360, // 向前旋转
  duration: 1, // 1秒转一圈,可以根据需要调整
  repeat: -1, // 无限循环
  ease: "linear", // 匀速
});
// 动画放到一个func里,视口到车的位置再执行
const animation = () => {
  // 每次animation方法调用,都让动画重新开始
  wheelAnimation.restart();
  gsap.killTweensOf([inner]);
  // 车从外面开进来
  gsap.fromTo(
    inner,
    {
      right: -500,
    },
    {
      right: 400,
      duration: 3,
      ease: "power1.inOut",
      onComplete: () => {
        // 车到位后,轮子停
        wheelAnimation.pause();
      },
    }
  );
};

// IntersectionObserver可以定义一个视口监听器,我们监听inner元素进入视口
const observer = new IntersectionObserver((entries) => {
  entries.forEach((entry) => {
    if (entry.isIntersecting) {
      // 进入后执行动画
      animation();
    }
  });
});

observer.observe(inner);

启动看下效果

pnpm dev

bandicam 2025-04-29 13-38-17-441.gif

结束

九折?就这!