为了实现一个响应式的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
): 根据鼠标的移动计算旋转角度并应用到照片墙上。 - 拖动结束 (
mouseup
和mouseleave
): 结束拖动状态。
关键代码注释
<!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