一、前言
之前写过《CSS3 动画简单入门》,文章内容只是简单介绍 CSS3 动画属性的使用,并没有一个综合的案例演示,因此本章作为前者的内容补充。
下面简单介绍本章需要实现的 3D 效果:
当加载页面后,图片展示“摊牌”的效果,当鼠标点击页面左滑动或者右滑动时,图片会跟随左旋转或右旋转。当鼠标点击页面上滑动或下滑动时,可以改变观察图片的角度。
二、实现
2.1 布局
<!DOCTYPE html>
<html onselectstart="return false">
<head>
<meta charset="utf-8">
<title>3D相册</title>
<link href="css/style.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div id="wrap" class="images">
<img src="images/01.png" alt="">
<img src="images/02.png" alt="">
<img src="images/03.png" alt="">
<img src="images/04.png" alt="">
<img src="images/05.png" alt="">
<img src="images/06.png" alt="">
<img src="images/07.png" alt="">
<img src="images/08.png" alt="">
<img src="images/09.png" alt="">
<img src="images/10.png" alt="">
<img src="images/11.png" alt="">
</div>
</div>
<script src="script/main.js"></script>
</body>
</html>
没有样式的效果图:
2.2 样式
style.css 文件内容:
* {
margin: 0px;
padding: 0px;
}
body {
background-color: #000;
}
.container {
perspective: 1500px;
}
.images {
width: 100px;
height: 100px;
margin: 150px auto;
position: relative;
transform: rotateX(-20deg);
transform-style: preserve-3d;/*切换 3D 效果*/
}
.images img {
position: absolute;
box-shadow: 0 0 8px #eee;
}
添加样式的效果图:
图片被设置 position: absolute; 后,所有图片重叠在一起了。
2.3 事件
从演示图中我们可以看出,3D 效果可以分 2 个步骤:摊牌效果和图片旋转效果。
2.3.1 摊牌效果
所有图片分摊 360 度,设置其旋转角度即可。
main.js 文件内容:
window.onload = function() {
var wrap = document.getElementById("wrap");
var images = document.getElementsByTagName("img");
var length = images.length;
var deg = 360 / length;
for (var i = 0; i < length; i++) {
images[i].style.transform = "rotateY(" + deg * i + "deg) translateZ(240px)";
images[length - i - 1].style.transition = "1s " + 0.2 * i + "s";
}
}
演示效果和动态图一样,此处省略。
所有图片包含在 div 中,当图片设置 rotateY 时,图片会以该 div 作为中心轴旋转。
图片还设置了 transition 属性,第一个参数表示过渡时间,第二个参数表示延迟时间。
2.3.2 旋转效果
实现图片旋转效果,只要改变中心轴的旋转角度即可。
main.js 文件完整内容:
window.onload = function() {
var wrap = document.getElementById("wrap");
var images = document.getElementsByTagName("img");
var length = images.length;
var deg = 360 / length;
for (var i = 0; i < length; i++) {
images[i].style.transform = "rotateY(" + deg * i + "deg) translateZ(240px)";
images[length - i - 1].style.transition = "1s " + 0.2 * i + "s";
}
// 点击坐标
var clickX, clickY;
// 移动坐标
var moveX, moveY;
// 移动距离坐标
var minusX, minusY;
// 旋转角度
var rotateX = 0,
rotateY = -20;
var timer = null;
// 鼠标按下事件
document.onmousedown = function(e) {
clickX = e.clientX;
clickY = e.clientY;
// 鼠标移动
this.onmousemove = function(e) {
moveX = e.clientX;
moveY = e.clientY;
// 移动距离
minusX = moveX - clickX;
minusY = moveY - clickY;
// 旋转角度,避免旋转太快故* 0.1
rotateX += minusX * 0.1;
rotateY -= minusY * 0.1;
// 中心轴旋转
wrap.style.transform = "rotateX(" + rotateY + "deg) rotateY(" + rotateX + "deg)"
clickX = moveX;
clickY = moveY;
}
// 鼠标释放
this.onmouseup = function() {
this.onmousemove = null;
// 旋转惯性
timer = setInterval(function() {
minusX *= 0.99;
minusY *= 0.98;
// 旋转角度
rotateX += minusX * 0.2;
rotateY -= minusY * 0.1;
// 中心轴旋转
wrap.style.transform = 'rotateX(' + rotateY + 'deg) rotateY(' + rotateX + 'deg) ';
if (Math.abs(minusX) < 0.1 && Math.abs(minusY) < 0.1) {
clearInterval(timer);
}
}, 10);
}
}
}