You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过页面滚动添加/移除类实现3D纸张弹出动画?

滚动控制纸张弹出3D动画实现方案

我需要实现一个动画:用户向下滚动页面时,一张纸张从插槽中向屏幕前弹出的3D效果,滚动操作控制纸张的进出。

我尝试过用多张代表不同弹出阶段的图片,通过滚动时添加/移除类来切换,但这个方法没法实现流畅动画,求最优解决方案。

我尝试的代码

HTML

<!DOCTYPE html>
<html lang="en" >
<head>
  <meta charset="UTF-8">
  <title>Scroll card flip</title>
  <link rel="stylesheet" href="style.css">


<body>
  
  <section class="one">
    <div class="parent">
    <div class="position_1">
      <img src="position_1.png"> 
    </div>

    <div class="position_2">
      <img src="position_2.png"> 
    </div>

    <div class="position_2">
      <img src="position_2.png"> 
    </div>

    <div class="position_3">
      <img src="position_3.png"> 
    </div>

    <div class="position_4">
      <img src="position_4.png"> 
    </div>

    <div class="position_5">
      <img src="position_5.png"> 
    </div>

    <div class="position_6">
      <img src="position_6.png"> 
    </div>
    </div>
  </section>
  <section class="two">
  </section>
  <section class="three">
  </section>
  
  <script  src="script.js"></script>

</body>
</html>

CSS

* {
  padding: 0;
  margin: 0;
}

section {
  height: 100vh;
  overflow: hidden;
}

.parent {
  width: 100vw;
  height: 100vh;
 display: flex;
 justify-content: center;
 place-items: center;
}

.one {
  background-color: greenyellow;
}

.two {
  background-color: orangered;
}

.three {
  background-color: aqua;
}

JavaScript

window.addEventListener('scroll', () => {

    const position_1 = document.querySelector('position_1');

 if(window.scrollY = 1) {  child.classList.add('position_1');}

 else if(window.scrollY = 2){
 child.classList.remove('position_1');
}

 if(window.scrollY = 2) {  child.classList.add('position_2');
 }

 else if(window.scrollY = 3){
 child.classList.remove('position_2');
 }

 if(window.scrollY = 3) {  child.classList.add('position_3');
 }

 else if(window.scrollY = 4){
  child.classList.remove('position_3');
  }

  if(window.scrollY = 4) {  child.classList.add('position_4');
 }

 else if(window.scrollY = 5){
  child.classList.remove('position_4');
  }

  if(window.scrollY = 5) {  child.classList.add('position_5');
}

else if(window.scrollY = 6){
  child.classList.remove('position_5');
  }

  if(window.scrollY = 6) {  child.classList.add('position_6');
}



  window.addEventListener('scroll',()=>{
    const scrolled = window.scrollY;
    console.log(scrolled);
  });})

最优解决方案

你的方法问题在于用离散的图片切换,很难做到流畅,而且JS逻辑里存在语法错误(比如用=赋值而非==/===判断、重复绑定scroll事件、child变量未定义等)。推荐用CSS 3D变换结合滚动监听,用单个元素实现连续动画:

实现思路

  • 用单个纸张元素,通过CSS transform的translateZ(控制前后位置)、rotateX(模拟弹出角度)实现3D效果
  • 监听滚动事件,根据滚动距离计算动画进度,动态更新纸张的变换属性
  • 父容器开启perspective属性,营造3D空间感

完整代码

HTML

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Scroll Paper Popup</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <section class="paper-section">
    <div class="slot">
      <div class="paper">
        <div class="paper-content">
          这是弹出的纸张
        </div>
      </div>
    </div>
  </section>
  <section class="placeholder-section"></section>
  <section class="placeholder-section"></section>

  <script src="script.js"></script>
</body>
</html>

CSS

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

section {
  height: 100vh;
}

.paper-section {
  background-color: greenyellow;
  display: flex;
  justify-content: center;
  align-items: center;
  perspective: 800px;
  overflow: hidden;
}

.slot {
  width: 300px;
  height: 400px;
  border: 3px solid #333;
  border-radius: 8px;
  position: relative;
  overflow: hidden;
  background-color: #fff;
}

.paper {
  width: 280px;
  height: 380px;
  background-color: #f9f9f9;
  position: absolute;
  top: 10px;
  left: 10px;
  transform-origin: bottom center;
  transition: transform 0.1s ease-out;
  box-shadow: 0 2px 10px rgba(0,0,0,0.2);
}

.paper-content {
  padding: 20px;
  font-size: 18px;
  color: #333;
}

.placeholder-section:nth-child(2) {
  background-color: orangered;
}

.placeholder-section:nth-child(3) {
  background-color: aqua;
}

JavaScript

const paper = document.querySelector('.paper');
const paperSection = document.querySelector('.paper-section');
const sectionTop = paperSection.offsetTop;
const sectionHeight = paperSection.offsetHeight;
const windowHeight = window.innerHeight;
const scrollRange = sectionHeight + windowHeight;

window.addEventListener('scroll', () => {
  const scrollY = window.scrollY;
  let progress = (scrollY - sectionTop + windowHeight) / scrollRange;
  progress = Math.max(0, Math.min(1, progress));

  const translateZ = progress * 200;
  const rotateX = progress * -30;
  
  paper.style.transform = `translateZ(${translateZ}px) rotateX(${rotateX}deg)`;
});

说明

  • 这个方案用连续的3D变换替代离散的图片切换,动画更流畅自然
  • 滚动进度和动画参数可以根据需求调整(比如translateZ的最大值、rotateX的角度)
  • 插槽和纸张的尺寸、样式可以自定义,适配你的设计需求

内容的提问来源于stack exchange,提问作者Jen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 11:15:55