HTML&CSS&JS:打造丝滑的3D彩纸飘落特效

0 阅读5分钟

这个 HTML 页面实现了一个动态、立体、色彩缤纷的彩纸(Confetti)飘落动画效果,常用于庆祝、成功提示或节日氛围营造。


大家复制代码时,可能会因格式转换出现错乱,导致样式失效。建议先少量复制代码进行测试,若未能解决问题,私信回复源码两字,我会发送完整的压缩包给你。

演示效果

演示效果

演示效果

HTML&CSS


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>彩纸</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
            background: #111;
            perspective: 1000px;
        }

        .confetti {
            position: absolute;
            top: -50px;
            transform-style: preserve-3d;
            animation: fall linear forwards;
        }

        .piece {
            position: relative;
            transform-style: preserve-3d;
            animation: spin linear infinite;
        }

        .side {
            position: absolute;
            width: 12px;
            height: 18px;
            backface-visibility: hidden;
        }

        .back {
            transform: rotateY(180deg);
            filter: brightness(0.6);
        }

        @keyframes fall {
            0% {
                transform:
                    translateY(0) translateZ(-800px) scale(0.3);
                opacity: 0.8;
            }

            100% {
                transform:
                    translateY(110vh) translateZ(300px) scale(1.4);
                opacity: 1;
            }
        }

        @keyframes spin {
            0% {
                transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg);
            }

            100% {
                transform: rotateX(720deg) rotateY(720deg) rotateZ(360deg);
            }
        }
    </style>
</head>

<body>
    <script>
        const colors = [
            "#ff0a54", "#ff477e", "#ff85a1",
            "#00f5d4", "#9b5de5",
            "#fee440", "#00bbf9"
        ];

        function createConfetti() {
            const confetti = document.createElement("div");
            confetti.classList.add("confetti");

            const piece = document.createElement("div");
            piece.classList.add("piece");

            const front = document.createElement("div");
            const back = document.createElement("div");

            front.classList.add("side");
            back.classList.add("side", "back");

            const color = colors[Math.floor(Math.random() * colors.length)];
            front.style.background = color;
            back.style.background = color;

            piece.appendChild(front);
            piece.appendChild(back);
            confetti.appendChild(piece);

            confetti.style.left = Math.random() * window.innerWidth + "px";

            const fallDuration = Math.random() * 4 + 4;
            const spinDuration = Math.random() * 3 + 2;

            confetti.style.animationDuration = fallDuration + "s";
            piece.style.animationDuration = spinDuration + "s";

            document.body.appendChild(confetti);

            setTimeout(() => {
                confetti.remove();
            }, fallDuration * 1000);
        }

        setInterval(createConfetti, 90);
    </script>
</body>

</html>

HTML

  • .confetti:每个彩纸的容器,控制整体下落动画。
  • .piece:单个彩纸片,负责旋转动画。
  • .side / .back:构成一个“双面”小矩形,模拟 3D 翻转效果。

CSS

1. 全局基础样式

body {
  margin: 0;
  overflow: hidden; /* 隐藏超出屏幕的彩纸,避免滚动条 */
  background: #111; /* 深黑背景,突出彩色纸片 */
  perspective: 1000px; /* 开启3D透视,数值越大透视感越弱,1000px是自然的3D效果 */
}

核心

  • perspective: 1000px 是 3D 特效的基础,让子元素的 3D 变换呈现「近大远小」的透视效果;
  • overflow: hidden 保证彩纸超出屏幕后不可见,避免页面出现滚动条。

2. 彩纸核心层级样式(3D 结构)

/_ 彩纸容器:控制整体飘落轨迹 _/
.confetti {
position: absolute;
top: -50px; /_ 初始位置在屏幕上方外,模拟从顶部飘落 _/
transform-style: preserve-3d; /_ 保留子元素的 3D 变换,不扁平化 _/
animation: fall linear forwards; /_ 飘落动画:匀速,结束后保持最终状态 _/
}

/_ 彩纸本体:控制旋转 _/
.piece {
position: relative;
transform-style: preserve-3d; /_ 子元素(正反面)保留 3D 变换 _/
animation: spin linear infinite; /_ 旋转动画:匀速,无限循环 _/
}

/_ 彩纸正反面:立体面 _/
.side {
position: absolute;
width: 12px;
height: 18px; /_ 长方形纸片,更贴近真实彩纸 _/
backface-visibility: hidden; /_ 隐藏背面(旋转时不会看到透明的反面) _/
}

.back {
transform: rotateY(180deg); /_ 反面绕 Y 轴旋转 180°,与正面背对 _/
filter: brightness(0.6); /_ 反面调暗,模拟立体纸片的阴影感 _/
}

核心 3D 结构

  • transform-style: preserve-3d:必须给父元素设置,否则子元素的 3D 变换会被扁平化(失去立体效果);
  • backface-visibility: hidden:避免旋转时看到纸片的「透明反面」,配合 rotateY(180deg) 实现「正反面分离」;
  • 反面调暗(brightness(0.6)):模拟真实纸片的厚度 / 阴影,增强 3D 立体感。

3. 动画关键帧

 /_ 飘落动画:从顶部到屏幕下方,伴随 3D 远近和缩放 _/
 @keyframes fall {
 0% {
 transform: translateY(0) translateZ(-800px) scale(0.3); /_ 初始:远、小、顶部 _/
 opacity: 0.8;
 }
 100% {
 transform: translateY(110vh) translateZ(300px) scale(1.4); /_ 结束:近、大、超出屏幕下方 _/
 opacity: 1;
 }
 }

/_ 旋转动画:3 轴同时旋转,模拟不规则飘落 _/
@keyframes spin {
0% {
transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg);
}
100% {
transform: rotateX(720deg) rotateY(720deg) rotateZ(360deg); /_ X/Y 轴转 2 圈,Z 轴转 1 圈 _/
}
}

核心动画设计

  • 飘落动画(fall):translateZ 控制 3D 远近(初始远、结束近),scale 配合实现「近大远小」;translateY(110vh) 让彩纸落到屏幕下方外,模拟「落地消失」;
  • 旋转动画(spin):X/Y/Z 三轴同时旋转,避免单一轴旋转的机械感,更贴近真实彩纸的不规则旋转;infinite 保证旋转持续到彩纸消失。

JavaScript

JS 的核心是「动态创建 + 随机化 + 自动清理」,实现无限且不规则的彩纸飘落效果。

// 1. 定义彩纸颜色数组:高饱和度亮色,视觉冲击力强
const colors = [
  "#ff0a54", "#ff477e", "#ff85a1", // 粉色系
  "#00f5d4", "#9b5de5",             // 青/紫系
  "#fee440", "#00bbf9"              // 黄/蓝系
];

// 2. 创建单张彩纸的核心函数
function createConfetti() {
  // 步骤1:创建彩纸DOM结构(层级:confetti → piece → front/back)
  const confetti = document.createElement("div");
  confetti.classList.add("confetti"); // 外层容器,控制飘落

  const piece = document.createElement("div");
  piece.classList.add("piece"); // 内层,控制旋转

  const front = document.createElement("div");
  const back = document.createElement("div");
  front.classList.add("side");
  back.classList.add("side", "back"); // 正反面

  // 步骤2:随机选择颜色,设置正反面背景
  const color = colors[Math.floor(Math.random() * colors.length)];
  front.style.background = color;
  back.style.background = color;

  // 步骤3:组装DOM结构
  piece.appendChild(front);
  piece.appendChild(back);
  confetti.appendChild(piece);

  // 步骤4:随机化关键参数,避免特效重复
  confetti.style.left = Math.random() * window.innerWidth + "px"; // 随机水平位置
  const fallDuration = Math.random() * 4 + 4; // 飘落时长:4-8秒(随机)
  const spinDuration = Math.random() * 3 + 2; // 旋转时长:2-5秒(随机)

  // 步骤5:给动画设置随机时长
  confetti.style.animationDuration = fallDuration + "s";
  piece.style.animationDuration = spinDuration + "s";

  // 步骤6:添加到页面
  document.body.appendChild(confetti);

  // 步骤7:自动清理元素(避免DOM堆积,优化性能)
  setTimeout(() => {
    confetti.remove(); // 飘落结束后删除元素
  }, fallDuration * 1000); // 延迟时间 = 飘落时长(毫秒)
}

// 3. 定时创建彩纸:每90毫秒创建一张,形成连续飘落效果
setInterval(createConfetti, 90);

各位互联网搭子,要是这篇文章成功引起了你的注意,别犹豫,关注、点赞、评论、分享走一波,让我们把这份默契延续下去,一起在知识的海洋里乘风破浪!