为了实现一个响应式的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