CSS3 中新增的一些还是相当强悍的,特别是在动画这方面,以前我们做动画基本都是用 JS 循环去实现,现在在 CSS3 中,我们直接用新增属性就能实现!短短几行代码,能获得远超 JS 的性能表现。今天我们就来探讨一下 CSS3 中关于 3D 动画的属性。
一、必不可少的perspective!
perspective的意思就是透视。很好理解,有没有这个参数,决定了你的3d转换效果是不是3d的,没有透视,谈何3d。
perspective定义的是视点距离显示器屏幕的距离。
当perspective的值取200px,意思是视点距离屏幕200px。当元素设置translateZ为100px时,相当于元素距离屏幕100px,那么从视点看到元素投影在屏幕上的大小就为原来的两倍!同理,当元素的translateZ值取-200px时,那么其在屏幕上的投影为原来的一半,我们看到的大小也为一半。
perspective的定义方式有两种,其中一种是设置父元素,另外一种是将其写在元素transform里,例如“transform: perspective(10px) translateZ(-10px)”。
其中设置父元素的方法针对的是整个舞台,其中所有的子元素公用一个视点;而写入transform里,则是把元素本身当成舞台进行3d转换。
二、perspective-origin的理解
其实和transform-origin一样,perspective-origin定义的是视点位置。正常情况下,translateZ会使元素相对于其中心点进行缩放,但如果加入“perspective-origin: 25% 70%”,其缩放中心就会发生变化。
三、transform-style: preserve-3d
preserve-3d,顾名思义,保持3d效果,就是讲当前元素的显示设置设为3D模式,其会影响子元素的相互遮盖。
四、backface-visibility
设置3d空间位置后面的元素可不可见,即遮不遮挡后面的元素。
五、实际应用(3D旋转相册)
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8"/>
<title>3D旋转相册</title>
<style>
/* 样式区 */
ul {
margin: 0;
padding: 0;
list-style: none;
}
#platform {
position: absolute;
left: 50%;
top: 50%;
width: 220px;
height: 220px;
margin: -110px;
perspective: 4000px;
}
#platform ul {
transform-style: preserve-3d;
animation: rotateY 16s linear infinite;
}
#platform ul li {
position: absolute;
}
#platform ul li img {
width: 220px;
box-shadow: 0 0 12px #888;
}
</style>
</head>
<body>
<div id="platform">
<ul>
<li><img src="./static/images/1.jpg" alt=""/></li>
<li><img src="./static/images/2.jpg" alt=""/></li>
<li><img src="./static/images/3.jpg" alt=""/></li>
<li><img src="./static/images/4.jpg" alt=""/></li>
<li><img src="./static/images/5.jpg" alt=""/></li>
<li><img src="./static/images/6.jpg" alt=""/></li>
</ul>
</div>
<script>
(function () {
var li = document.getElementsByTagName("li");
var width = li[0].offsetWidth;
var angle = 360 / li.length;//计算旋转角(deg)
var offset = (width / 2) / Math.tan(Math.PI / li.length) + 20;//计算每个展示位偏移距离
//设置每个展示位的角度及其偏移量
for (var i = 0; i < li.length; i++) {
li[i].style.transform = "rotateY(" + angle * i + "deg) translateZ(" + offset + "px)";
localto(i);
}
//点击快速旋转定位
function localto(index) {
li[index].onclick = function () {
clearInterval(window.timer2);
var ul = this.parentNode;
var curA = a;
var resultA = -angle * index;
timer2 = setInterval(function () {
if (parseInt(curA) == parseInt(resultA)) {
clearInterval(timer2);
timer2 = null;
} else if (curA < resultA) {
if (Math.abs(curA - resultA) > 180) {
resultA -= 360;
curA -= 0.8;
} else {
curA += 0.8;
}
} else {
if (Math.abs(curA - resultA) > 180) {
resultA += 360;
curA += 0.8;
} else {
curA -= 0.8;
}
}
a = curA;
ul.style.transform = "rotateY(" + curA + "deg)";
}, 10);
}
}
var a = 0;
//循环播放
function play() {
timer1 = setInterval(function () {
if (!window.timer2) {
var ul = document.getElementsByTagName("ul")[0];
if (a <= -360) {
a = 0;
}
ul.style.transform = "rotateY(" + a + "deg)";
a -= 0.25;
}
}, 20);
}
//悬浮暂停
document.getElementById("platform").onmouseover = function (e) {
clearInterval(timer1);
};
//移开继续动画
document.getElementById("platform").onmouseout = function (e) {
play();
}
play();
})()
</script>
</body>
</html>