原文: 張鑫旭老師的 好吧,CSS3 3D transform變換陶贼,不過如此!待秃。
參考資料:w3school ||
CSS 3D Panorama - 淘寶造物節(jié)技術剖析
|| transform-function
|| 《css揭秘》
先來介紹以下transform 有哪些值:
- none 定義不進行轉換
- martix(n,n,n,n,n,n) 定義2D轉換拜秧,使用六個值的矩陣
- martix3d(n,n,n,n,n,n,n,n,n,n,n,n,n,n,n,n) 定義3D轉換,使用16個值的4*4矩陣
- translate(x, y) 定義2D轉換
- translate3d(x, y, z) 定義3D轉換
- translateX(x) 定義轉換章郁,只用 X 軸的值
- translateY(y) 定義轉換枉氮,只用 y 軸的值
- translateZ(z) 定義3D轉換,只用 z 軸的值
- scale(x,y) 定義2D縮放轉換
- scale3d(x, y, z) 定義3D縮放轉換
- scaleX(x) 設置 x 軸的值來定義縮放轉換
- scaleY(y) 設置 y 軸的值來定義縮放轉換
- scaleZ(z) 設置 z 軸的值來定義縮放轉換
- rotate(angle) 定義2D轉換暖庄,在參數(shù)中規(guī)定角度
- rotate3d(x, y, z, angle) 定義3D轉換
- rotateX(angle) 沿著 x 軸的3D旋轉
- rotateY(angle) 沿著 y 軸的3D旋轉
- rotateZ(angle) 沿著 z 軸的3D旋轉
- skew(x-angle, y-angle) 沿著x和y軸的2D傾斜轉換
- skewX(angle) 沿著 x 軸的2D傾斜轉換
- skewY(angle) 沿著 y 軸的2D傾斜轉換
- perspective(n) 為3D 轉換元素定義透視視圖
如果以電腦屏幕為參考物的話聊替,x軸就是電腦屏幕的長, y軸就是電腦屏幕的寬培廓,z軸就是眼睛直視電腦屏幕的距離惹悄,那么就會得到下面一張側視圖:
在開始之前先解釋一下幾個值:
perspective: 指定觀察者與 z = 0 平面的距離,使具有三維位置變換的元素產生透視效果肩钠。(默認值:none泣港,值只能是絕對長度)
transform-style:用于指定其子元素提供2D還是3D的場景。 值: flat | preserve-3d
backface-visiblity: 確定當面對用戶時元素背面是否可見 值: visible | hidden
perspective-origin: 決定觀察者正在查找的位置价匠,該位置就會消失
transform-box:transform-box屬性定義了transform和transform-origin屬性所關聯(lián)的布局框当纱。值: border-box | fill-box | view-box
transform-origin: 修改元素的變換原點 值: x-offset-keyword | y-offset-keyword | z-offset
我們都知道物體離的越近物體就越大,離的越遠物體就越小即: 當translateZ的值小于perspective的值時踩窖,物體就越大坡氯,當translateZ的值大于perspective的值時,物體消失。
實例: 圖片的旋轉木馬效果
原理: 讓圖片共用公共點箫柳,利用rotateY決定圖片朝向手形。
關鍵點: 使用translateZ 遠離原點
translateZ 計算:
代碼:
html
<div class="stage">
<div class="container">
![](img.jpg)
![](img1.jpg)
![](img2.jpg)
![](img.jpg)
![](img1.jpg)
![](img2.jpg)
![](img.jpg)
![](img1.jpg)
![](img2.jpg)
![](img.jpg)
</div>
</div>
css
* {
padding: 0;
margin: 0;
font-size: 14px;
}
.stage {
perspective: 800px;
width: 80%;
margin: 20% auto;
}
.container {
position: relative;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-ms-transform-style: preserve-3d;
-o-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transition: -webkit-transform 1s;
-moz-transition: -moz-transform 1s;
-ms-transition: -ms-transform 1s;
-o-transition: -o-transform 1s;
transition: transform 1s;
}
img {
width: 128px;
height: 100px;
position: absolute;
left: 50%;
margin: 0 0 0 -64px;
}
.pic {
position: absolute;
bottom: 0;
border-radius: 2px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
-webkit-transition: opacity 1s, -webkit-transform 1s;
-moz-transition: opacity 1s, -moz-transform 1s;
-ms-transition: opacity 1s, -ms-transform 1s;
-o-transition: opacity 1s, -o-transform 1s;
transition: opacity 1s, transform 1s;
backface-visibility:hidden;
}
img:nth-child(1){ transform: rotateY(0deg) translateZ(195.839px); }
img:nth-child(2){ transform: rotateY(40deg) translateZ(195.839px); }
img:nth-child(3){ transform: rotateY(80deg) translateZ(195.839px); }
img:nth-child(4){ transform: rotateY(120deg) translateZ(195.839px); }
img:nth-child(5){ transform: rotateY(160deg) translateZ(195.839px); }
img:nth-child(6){ transform: rotateY(200deg) translateZ(195.839px); }
img:nth-child(7){ transform: rotateY(240deg) translateZ(195.839px); }
img:nth-child(8){ transform: rotateY(280deg) translateZ(195.839px); }
img:nth-child(9){ transform: rotateY(320deg) translateZ(195.839px); }
img:nth-child(10){ transform: rotateY(360deg) translateZ(195.839px); }
js
// CSS transform 變換應用
(function() {
var transform = function(el, val, key) {
key = key || 'Transform';
['Moz', 'Ms', 'Webkit', 'o', ''].forEach(function(prefix) {
el.style[prefix + key] = val;
});
return el;
},
// 瀏覽器選擇器API
$ = function(selector) {
return document.querySelector(selector);
},
$$ = function(selector) {
return document.querySelectorAll(selector);
}
var imgArr = document.getElementsByClassName('pic');
var eleStage = $('.stage'), eleContent = $('.container'), indexPic = 0,
elePic = $$('pic'), transZ = 64 / Math.tan((2 / 180) * Math.PI);
var rotate = 400 / imgArr.length;
eleContent.addEventListener('click', function() {
transform(this, 'rotateY(' + (- 1 * rotate * ++indexPic) + 'deg)');
});
imgArr.forEach(function(j) {
transform($('.pic' ), 'rotateY(' + j * rotate + 'deg) translateZ(' + (transZ + 20) + 'px)');
})
})()
拓展實例:
模擬開門特效(反方向)
突然來了靈感,當然以前也看過同樣的效果滞时,當時很不解叁幢,不知道怎么實現(xiàn),現(xiàn)在終于可以實現(xiàn)相類似的效果了坪稽。
使用到的屬性:
- transform-style
- rotateY
- transform-origin
- animation-timing-function
- cubic-bezier
- animation
效果圖:
代碼:
html
<form action="#" class="form">
<label for="username">
<i>用戶名:</i><input type="text" class="username" name="username"></label>
<label for="password">
<i>密碼:</i><input type="password" class="username" name="password"></label>
<button class="login-text" type="button">登錄</button>
</form>
<div class="login">
<button class="login-text" type="button">登錄</button>
</div>
css
* {
margin: 0;
padding: 0;
}
body {
perspective: 500px;
}
.form {
position: relative;
display: block;
width: 450px;
height: 450px;
margin: 10% auto;
background: #3B445B;
border-radius: 4px;
transform-style: preserve-3d;
transform: rotateY(0deg);
transform-origin: 0 0;
color: #f0f0f0;
animation: login-rotate 3s;
}
label {
float: left;
margin: 70px 0 0 70px;
}
.login {
position: absolute;
top: 50%;
left: 50%;
width: 400px;
height: 400px;
margin: -200px 0 0 -200px;
transform: scale(0);
background: #3B445B;
border-radius: 4px;
transform-origin: center;
animation: login-show 3s;
}
.username {
margin: 0 20px;
padding: 3px 0;
width: 200px;
font-size: 18px;
}
.login-text {
position: absolute;
bottom: 40px;
left: 70px;
width: 300px;
height: 40px;
border-radius: 4px;
background: #49D292;
border: none;
color: #f0f0f0;
font-size: 16px;
}
i {
width: 70px;
float: left;
font-style: normal;
}
@keyframes login-show {
from {
transform: scale(0);
/*opacity: 0;*/
}
10% {
opacity: 0.8;
}
80% {
transform: scale(1.1);
/*opacity: 1;*/
animation-timing-function: cubic-bezier(.1, .25, .3, 1.5);
}
90% {
/*opacity: 0;*/
}
}
@keyframes login-rotate {
from {
transform: rotateY(0deg);
opacity: 1;
}
10% {
opacity: 1;
}
80% {
transform: rotateY(90deg);
opacity: 0;
}
}
Ps: 這只是單純的實現(xiàn)了特效還未與js相結合曼玩、后端數(shù)據(jù)結合。