上一篇寫遺留下來幾個(gè)問題:
1、如果是正多面體怎么辦?
正四面體,我們可以輕松確定translateZ 的值為元素的寬的一半。那如果是正五面體呢,正N面體呢?先不急,哥先畫個(gè)圖,分析一下。
以一個(gè)正五邊形為例:我們最終的目的是求到AO的距離,這個(gè)距離就是我們要進(jìn)行平移(translateZ)的值 , 會(huì)涉及到簡單的數(shù)學(xué)知識(shí),正N邊形的外角邊之和永遠(yuǎn)是360度。
那么我們可以算出來角度b = 360 / N 度 ,求出b 再來算a就簡單了 角度a = (180-b) / 2,求出角度a了,AB為元素寬的一半,要求出AO的距離,就容易了。AO = Math.tan(Math.PI/180*a) * AB ,一個(gè)簡單的三角正切就能實(shí)現(xiàn)了。
再來計(jì)算下每個(gè)面的旋轉(zhuǎn)的角度應(yīng)該為 360 / N * index 度。
好了,接下來直接上代碼了。
Document
*{margin:0;padding: 0;}
html,body{
width: 100%;
height: 100%;
font-size:30px;
}
.zmiti-box{
width: 300px;
height: 300px;
position: absolute;
left: 0;
top:200px;
perspective:1800px;
left: 50%;;
margin-left: -150px;
}
.zmiti-box section{
transform-style: preserve-3d;
position:relative;
width: 100%;
height: 100%;
left: 0;
transition:5s;
}
.zmiti-box .zmiti-box-item{
position: absolute;
left: 0;
top:0;
width: 100%;
height: 100%;
line-height: 300px;
color:#fff;
font-size:80px;
text-align:center;
}
var zmitiUtil = {
length:10,//我要?jiǎng)?chuàng)建正20面體
init(){
this.createElement();
this.bindEvent();
},
createElement(){
this.box = document.querySelector('.zmiti-box section');
var html = '';
var elWidth = 300;//元素的寬度,也可以通過獲取元素的clientWidth,我這就硬編碼寫死了。
var angle = 360 / this.length;
var translateZ = Math.tan(Math.PI / 180 * (180 - angle) / 2) * elWidth / 2;
for(var i = 0 ;i < this.length ;i++){
html+= `
};
this.box.innerHTML = html;
},
bindEvent(){
document.body.addEventListener('touchstart',()=>{
this.box.style.transform = 'rotateY(360deg) rotateX(60deg)';
});
}
};
zmitiUtil.init();
效果如下:
但是這個(gè)好像沒什么卵用啊,造物節(jié)那個(gè)感覺人站在圓柱中間看的,應(yīng)該是這樣的效果
我們改造下,我們把每個(gè)元素的translateZ取反為負(fù)值,然后再設(shè)置背面隱藏就ok了。
.zmiti-box .zmiti-box-item{
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
}
記得在移動(dòng)端要加上webkit前綴。否則無效哦。
最后的就是把每個(gè)面用一張張的圖片拼起來的了,原理是用一張長圖,平均切成N份,然后填充成背景就搞定了哦。
移動(dòng)端的適配問題:可以動(dòng)態(tài)設(shè)置最外層父級(jí)的景深值來做下控制。這里就不再做贅述了。大家可以自己研究下。