3D照片墙

为了实现一个响应式的3D照片墙展示特效,我们可以使用HTML、CSS和JavaScript。这个特效将允许用户通过鼠标移动来旋转照片墙,同时保持响应式设计以便在不同设备上都能良好显示。每个图片框架的位置和角度都进行了预设,以形成一个立体的效果。你可以根据需要替换图片链接以显示不同的图像。

以下是代码的关键点总结:

HTML结构

  • <div class="photo-wall-container">: 包含整个3D照片墙的容器。
  • <div class="photo-wall">: 实际的照片墙元素,包含多个图片框架。
  • <div class="photo-frame">: 每个图片框架,包含一个图片。

CSS样式

  • .photo-wall-container: 设置容器的大小和透视效果。
  • .photo-wall: 设置照片墙的3D变换效果和过渡动画。
  • .photo-frame: 设置每个图片框架的大小、边框和背景颜色,并应用3D变换效果。
  • .photo-frame img: 设置图片的显示方式和隐藏背面。
  • .photo-frame:nth-child(n): 预设每个图片框架的位置和角度,形成3D立体效果。

JavaScript交互

  • 拖动开始 (mousedown): 记录鼠标按下时的位置。
  • 鼠标移动 (mousemove): 根据鼠标的移动计算旋转角度并应用到照片墙上。
  • 拖动结束 (mouseupmouseleave): 结束拖动状态。

关键代码注释

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>响应式3D照片墙展示特效</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #f4f4f9;
            overflow: hidden;
        }
        .photo-wall-container {
            position: relative;
            width: 100vw; /* 宽度占视口宽度的100% */
            height: 100vh; /* 高度占视口高度的100% */
            perspective: 1000px; /* 设置透视效果 */
        }
        .photo-wall {
            position: absolute;
            width: 100%;
            height: 100%;
            transform-style: preserve-3d; /* 保持3D变换效果 */
            transition: transform 0.5s ease; /* 平滑过渡效果 */
        }
        .photo-frame {
            position: absolute;
            width: 20%; /* 每个框架宽度占容器宽度的20% */
            height: 20%; /* 每个框架高度占容器高度的20% */
            box-sizing: border-box;
            border: 2px solid #fff; /* 边框颜色为白色 */
            background-color: #fff; /* 背景颜色为白色 */
            transform-style: preserve-3d; /* 保持3D变换效果 */
            transition: transform 0.5s ease; /* 平滑过渡效果 */
        }
        .photo-frame img {
            width: 100%;
            height: 100%;
            object-fit: cover; /* 图片覆盖整个框架 */
            backface-visibility: hidden; /* 隐藏背面 */
        }
        /* Positioning frames */
        .photo-frame:nth-child(1) { transform: translateZ(300px); } /* 前面 */
        .photo-frame:nth-child(2) { transform: rotateY(90deg) translateZ(300px); } /* 右侧 */
        .photo-frame:nth-child(3) { transform: rotateY(180deg) translateZ(300px); } /* 后面 */
        .photo-frame:nth-child(4) { transform: rotateY(270deg) translateZ(300px); } /* 左侧 */
        .photo-frame:nth-child(5) { transform: rotateX(90deg) translateZ(300px); } /* 上方 */
        .photo-frame:nth-child(6) { transform: rotateX(-90deg) translateZ(300px); } /* 下方 */
        .photo-frame:nth-child(7) { transform: translateX(150px) translateY(150px) translateZ(200px); } /* 右上前方 */
        .photo-frame:nth-child(8) { transform: translateX(-150px) translateY(-150px) translateZ(200px); } /* 左下后方 */
        .photo-frame:nth-child(9) { transform: translateX(150px) translateY(-150px) translateZ(200px); } /* 右下前方 */
        .photo-frame:nth-child(10) { transform: translateX(-150px) translateY(150px) translateZ(200px); } /* 左上前方 */
    </style>
</head>
<body>
    <div class="photo-wall-container">
        <div class="photo-wall">
            <div class="photo-frame"><img src="https://syjm.net/public/demo_s.webp" alt="Image 1"></div>
            <div class="photo-frame"><img src="https://syjm.net/public/demo_s.webp" alt="Image 2"></div>
            <div class="photo-frame"><img src="https://syjm.net/public/demo_s.webp" alt="Image 3"></div>
            <div class="photo-frame"><img src="https://syjm.net/public/demo_s.webp" alt="Image 4"></div>
            <div class="photo-frame"><img src="https://syjm.net/public/demo_s.webp" alt="Image 5"></div>
            <div class="photo-frame"><img src="https://syjm.net/public/demo_s.webp" alt="Image 6"></div>
            <div class="photo-frame"><img src="https://syjm.net/public/demo_s.webp" alt="Image 7"></div>
            <div class="photo-frame"><img src="https://syjm.net/public/demo_s.webp" alt="Image 8"></div>
            <div class="photo-frame"><img src="https://syjm.net/public/demo_s.webp" alt="Image 9"></div>
            <div class="photo-frame"><img src="https://syjm.net/public/demo_s.webp" alt="Image 10"></div>
        </div>
    </div>

    <script>
        const photoWallContainer = document.querySelector('.photo-wall-container');
        const photoWall = document.querySelector('.photo-wall');

        let isDragging = false;
        let startX, startY;
        let currentRotateX = 0;
        let currentRotateY = 0;

        // 开始拖动事件
        photoWallContainer.addEventListener('mousedown', (e) => {
            isDragging = true;
            startX = e.pageX - photoWall.offsetLeft; // 记录初始鼠标位置
            startY = e.pageY - photoWall.offsetTop;
        });

        // 鼠标移动事件
        window.addEventListener('mousemove', (e) => {
            if (!isDragging) return; // 如果没有拖动则返回
            const deltaX = e.pageX - photoWall.offsetLeft - startX; // 计算水平偏移量
            const deltaY = e.pageY - photoWall.offsetTop - startY; // 计算垂直偏移量

            currentRotateY += deltaX * 0.1; // 更新旋转角度
            currentRotateX -= deltaY * 0.1;

            photoWall.style.transform = `rotateX(${currentRotateX}deg) rotateY(${currentRotateY}deg)`; // 应用旋转效果

            startX = e.pageX - photoWall.offsetLeft; // 更新起始位置
            startY = e.pageY - photoWall.offsetTop;
        });

        // 结束拖动事件
        window.addEventListener('mouseup', () => {
            isDragging = false;
        });

        // 离开窗口结束拖动
        window.addEventListener('mouseleave', () => {
            isDragging = false;
        });
    </script>
</body>
</html>

No responses yet

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注