點點動畫~畫出懂你的3D魔方

做者:首席填坑官∙蘇南
來源:@IT·平頭哥聯盟
公衆號:honeyBadger8css

前言

  最近在寫《點點動畫系列》文章,上一期分享了< 手把手教你如何繪製一輛會跑的車 >,本期給你們帶來是結合CSS3畫出來的一個立體3d魔方,結合了js讓你爲所欲爲想怎麼轉,就怎麼轉,這裏是 @IT·平頭哥聯盟,我是首席填坑官蘇南(South·Su),咱們先來看看效果,而後再分解它的實現過程吧html

本文由@IT·平頭哥聯盟-首席填坑官∙蘇南分享,每週動畫一點點之CSS3畫出懂你的3D魔方
作有溫度的攻城獅,CSS3畫出懂你的3D魔方

繪製過程:

  好吧,gif圖看着好像有點不是很清晰,想在線預覽的同窗,可點擊在線預覽 👈,廢話很少扯了,先來分析一下,看如何實現這個功能吧。前端

∙ API預熱 :
  • 本次示例是一個立體的正方形,既然有立體效果,確定少不了CSS3中的 -webkit-perspective-透視、preserve-3d-三維空間,這個兩個是重點哦,固然還有transform-origintransitiontransform等,先來回故一下 API 怎麼是講的吧:

perspective 取值 :css3

  • none :不指定透視 ;
  • length :指定觀察者與「z=0」平面的距離,使具備三維位置變換的元素產生透視效果。「z>0」的三維元素比正常大,而「z<0」時則比正常小,大小程度由該屬性的值決定,不容許負值。

transform-style 取值git

  • flat :指定子元素位於此元素所在平面內;
  • preserve-3d :指定子元素定位在三維空間內,當該屬性值爲 preserve-3d時,元素將會建立局部堆疊上下文;

小結 :決定一個變換元素看起來是處在三維空間仍是平面內,須要該元素的父元素上定義 <' transform-style '> 屬性,也就是說想某元素有三維效果,須要設定它的父級有 preserve-3dgithub

transform-origin 取值web

  • percentage:用百分比指定座標值。能夠爲負值;
  • length:用長度值指定座標值。能夠爲負值;
  • left:指定原點的橫座標爲left;
  • center①:指定原點的橫座標爲center;
  • right:指定原點的橫座標爲right;
  • top:指定原點的縱座標爲top;
  • center②:指定原點的縱座標爲center;
  • bottom:指定原點的縱座標爲bottom;

transform、transition等,就不介紹了ruby

/* perspective 使用示例:*/
div{
	-webkit-perspective:600px;
	perspective:600px;
}

/*transform-style 使用示例:*/
.preserve{
	transform-style:preserve-3d;
	-webkit-transform-style:preserve-3d;
}

  /*transform-origin 使用示例:*/
.preserve{
	-webkit-transform-origin:50% 50% -100px; or 
	-webkit-transform-origin:bottom; or
	-webkit-transform-origin:top;
	…………
}
  

複製代碼
∙ 繪製6個面 :
  • 是的,我沒有說錯,就是6個面:上、正面、下、背面、左、右,
  • 上面API講了這麼多,來實踐試一下吧,寫6個div,結構大概是這樣的,也是接下來的魔方須要的結構:
<div class="cube">
    <div class="cube-inner running">
        <p class="single-side s1"><span></span></p>
        <p class="single-side s2"><span></span></p>
        <p class="single-side s3"><span></span></p>
        <p class="single-side s4"><span></span></p>
        <p class="single-side s5"><span></span></p>
        <p class="single-side s6"><span></span></p>
    </div>
</div>

複製代碼

每週動畫一點點之 perspective的演示
每週動畫一點點之 perspective的演示

  • !!!發生了什麼??是否是很吃驚??說好的值越大,透視效果越強的呢?後面明明藏了個妹子,怎麼看沒有透視出來?
  • 開始我也是跟你同樣吃驚的,但瞬間就悟透了,少了rotate,加個它再來看看效果吧:

本文由@IT·平頭哥聯盟-首席填坑官∙蘇南分享,每週動畫一點點之 transform的演示

.cube{
    width:200px;
    height:200px;
    margin:10px auto;
    padding:260px;
    position:relative;
    -webkit-perspective:600px;
    perspective:600px;
    transition: .5s ;

}
.cube-inner{
    width:200px;
    height:200px;
    position:relative;
    -webkit-transform-style:preserve-3d;
    transition:.3s; 
    -webkit-transform-origin:50% 50% -100px;
    transform: rotateX(45deg);
}
.cube:hover{
    /*鼠標通過時,把 perspective 過渡到100 */
    -webkit-perspective:100px;
    perspective:100px;
}

複製代碼
  • 既然API有效,那麼拉下來咱們就畫出6個面吧,按:上、正面、下、背面、左、右,這個順序來設置吧;
  • 首先,咱們要指定它們是在三維空間內的preserve-3d,也就是6個面的父級要設置 transform-style 樣式;
  • 以上都設置好後,再來看看6個面吧,爲了便於區分,給它們每一個都設置了不一樣顏色(用了css3的漸變 radial-gradient)——不想手寫的同窗推薦一個網站可在線設置你要的效果,複製樣式便可,先來一睹風采,爲了便於觀察,總體角度旋轉了10deg:

每週動畫一點點之 6個面的元素的演示

  • 說到漸變,偶然之間發現了一個有意思的東西hue-rotate,它能在你初始的顏色基礎上旋轉元素的色調及其內容,從而達到不一樣的效果。瞭解更多

hue-rotate : The hue-rotate() CSS function rotates the hue of an element and its contents. Its result is a .ide

每週動畫一點點之hue-rotate,本文由@IT·平頭哥聯盟-首席填坑官∙蘇南分享

  • - "":
.cube-inner .single-side.s1{
    /*s1頂部*/
    left:0;top:-200px;
    background: radial-gradient(circle, rgba(255,255,255,.88), #00adff);
    background: -webkit-radial-gradient(circle, rgba(255,255,255,.88), #00adff);
    transform-origin:bottom;
    -webkit-transform-origin:bottom;
    transform:rotateX(90deg);
    -webkit-transform:rotateX(90deg);
}
複製代碼

每週動畫一點點之 6個面的元素之上

  • 正面 - "":佈局

    • 下面就是默認的,什麼都不用設置,因此就不展現了 ;
  • 下面 - "":

    • 即底部,底部的設置,正好跟頂部它是相反的,一個origin 以 bottom爲基準爲座標,一個以top爲基準爲座標;
.cube-inner .single-side.s3{
    /*s3底部*/
    left:0;top:200px;
    background: radial-gradient(circle, rgba(255,255,255,.88), #100067);
    background: -webkit-radial-gradient(circle, rgba(255,255,255,.88), #100067);
    transform-origin:top;
    -webkit-transform-origin:top;
    transform:rotateX(-90deg);
    -webkit-transform:rotateX(-90deg);
}
複製代碼

本文由@IT·平頭哥聯盟-首席填坑官∙蘇南分享,每週動畫一點點之 6個面的元素之底部

  • 背面 - "":
    • 即正面的後邊,總體旋轉了 135deg,讓背面更直觀能看到;
    • translateZ 、rotateX 同時移動,造成透視的關係,讓它看起來,在正面面的後面;
    • 下圖二,把默認的正面,設置了透明度,能夠看出,背面的透視效果;
.cube-inner .single-side.s4{
    /*s4背部*/
    z-index:2;
    left:0;top:0;
    background: radial-gradient(circle, rgba(255,255,255,.88), #F0C);
    background: -webkit-radial-gradient(circle, rgba(255,255,255,.88), #F0C);
    transform:translateZ(-200px) rotateX(180deg) ; 
    -webkit-transform:translateZ(-200px) rotateX(180deg) ; /*rotateZ(-180deg) 左右旋轉的時候,Z軸旋轉180°,由於字是倒着的*/
}
複製代碼

每週動畫一點點之 6個面的元素之背面
本文由@IT·平頭哥聯盟-首席填坑官∙蘇南分享

  • 左側面 - "":
    • origin以right爲基準,left負元素的寬度,rotateY軸旋轉90deg;
.cube-inner .single-side.s5{
    /*s5左側*/
    left:-200px;top:0;
    background: radial-gradient(circle, rgba(255,255,255,.88),rgba(33,33,33,1));
    background: -webkit-radial-gradient(circle, rgba(255,255,255,.88),rgba(33,33,33,1));
    transform-origin:right;
    -webkit-transform-origin:right;
    transform:rotateY(-90deg)
    -webkit-transform:rotateY(-90deg)
}
複製代碼

每週動畫一點點之 6個面的元素之左側面

  • 右側面 - "":
    • 同理右側,與左側正好相反;
.cube-inner .single-side.s6{
    /*s6右側*/
    right:-200px;top:0;
    transform-origin:left;
    -webkit-transform-origin:left;
    background: radial-gradient(circle, rgba(255,255,255,.88), #f00);
    background: -webkit-radial-gradient(circle, rgba(255,255,255,.88), #f00);
    transform:rotateY(90deg);
    -webkit-transform:rotateY(90deg);
}
複製代碼

每週動畫一點點之 6個面的元素之左側面
本文由@IT·平頭哥聯盟-首席填坑官∙蘇南分享

小結 : 嗯,以上魔方的6個面的繪製過程,基本已經完成,主要在在於transform-originrotatetranslate等屬性的應用,但爲了讓它更炫酷一些,咱們還要給邊角加一些光感。

∙ 添加高光 :
  • 細心的寶寶,前面的佈局應該已經發現了,每一行佈局的p標籤裏,都多套了一層span,就是爲高光光感,埋下的伏筆,一個平面正方形有四個邊,after、before只有兩,那麼確定要再套一層,固然方法不少,好比直接用border也是能夠的,但比較麻煩,我就選擇瞭如今要講的這種:
  • after、before設置1px的邊框,設置一個線性漸變,中間是白色,兩斷是過渡到透明的,這樣高光就有了,來看一組圖吧:

每週動畫一點點之 6個面的元素高光感
每週動畫一點點之 6個面的元素鼠標通過
6個面的元素鼠標通過

∙ CSS 360°旋轉 :
  • 上面是一個鼠標通過的過渡動畫,能夠看出立體效果是已經有了,接下來就寫一個CSS animation的動畫,讓它360度旋轉,每一個角都能看到,這樣會顯的很666;
  • animation 配合 keyframes 使用,請看代碼示例:
.cube .cube-inner{ 
	/*-webkit-transform:rotateX(180deg) rotateY(0deg) ;*/
	animation: elfCube 10s infinite ease-in-out;
	-webkit-animation: elfCube 10s infinite ease alternate;
}

@keyframes elfCube {
	0% { 
		transform: rotateX(0deg) rotateY(0deg); 
	}
	50% { 
		transform: rotateX(360deg) rotateY(360deg); 
	}
	100% { 
		transform: rotateX(0deg) rotateY(0deg); 
	}
}
@-webkit-keyframes elfCube {
	0% {
	 -webkit-transform: rotateX(0deg) rotateY(0deg); 
	}
	50% {
	 -webkit-transform: rotateX(360deg) rotateY(360deg); 
	}
	100% { 
		transform: rotateX(0deg) rotateY(0deg); 
	}
}
複製代碼

每週動畫一點點之 6個面的元素之360度旋轉,由@IT·平頭哥聯盟-首席填坑官∙蘇南分享
CSS 360度旋轉

∙ 跟隨鼠標旋轉 :
  • 說好的隨着鼠標旋轉呢??
  • 別慌,接下來就是帶你裝逼,帶你飛的時候,
    • 首先咱們要了解,鼠標在容器內所在的位置,X = e.pageX - ele.offsetLeft, Y = e.pageY - ele.offsetTop;
    • 同時要知道元素內的中心點:centerX = width/2,centerY =height/2;
    • 而後得出值:axisX = X - centerX,axisY = Y - centerY;
    • PS : 開始嘗試想的是鼠標從哪一個方向進入,獲得它的角度,但發現旋轉效果不明顯 ,有興趣的同窗能夠嘗試一下:(((Math.atan2(Y, X) * (180 / Math.PI)) + 180) / 90),參考司徒大神的JS判斷鼠標從什麼方向進入一個容器;
    • 最後,給容器綁上事件:mouseovermousemovemouseout,鼠標進入時,暫停css的動畫,否則會相互打架哦!

每週動畫一點點之 6個面的元素之360度旋轉,由@IT·平頭哥聯盟-首席填坑官∙蘇南分享
每週動畫一點點之360度旋轉

……
getAxisX(e){
	let left = this.cubeEle.offsetLeft;
	return e.pageX - left - (this.cubeW/2) * (this.cubeW>this.cubeH ? this.cubeH/this.cubeW : 1);
}
getAxisY(e){
	let top = this.cubeEle.offsetTop;
	return e.pageY - top - (this.cubeH/2) * (this.cubeH>this.cubeW ? this.cubeW/this.cubeH : 1);
}
 …………

複製代碼
…………
run(){
	this.cubeEle.addEventListener('mouseover',(e)=>this.hoverOut(e),false);
	this.cubeEle.addEventListener('mousemove',(e)=>this.move(e),false);
	this.cubeEle.addEventListener('mouseout',(e)=>this.hoverOut(e),false);
}
hoverOut(e){
	//進入/離開
	e.preventDefault();
	this.axisX = this.getAxisX(e),
	this.axisY = this.getAxisY(e);

	if(e.type == 'mouseout'){ //離開
		this.axisX=0;
		this.axisY = 0;
		console.log("離開")
		this.cubeInner.className="cube-inner running";
	}else{
		this.cubeInner.className="cube-inner";
		console.log("進入")
	};
	let rotate = `rotateX(${-this.axisY}deg) rotateY(${-this.axisX}deg)`;
	this.cubeInner.style.WebkitTransform = this.cubeInner.style.transform = rotate;
}
 ……
複製代碼

結尾:

  • -webkit-perspective,
  • -webkit-transform-style,
  • -webkit-transform-origin,
  • radial-gradient、linear-gradient,
  • transform:rotate、translate、scale,
  • transition,
  • animation;
  • 以上就是今天爲你們帶來的分享,以及使用到的知識點的API,如文章中有不對之處,煩請各位大神斧正,也歡迎關注下方的 公衆號
  • 文章源碼獲取-> blog-resource 👈
  • 想直接在線預覽 👈

寶劍鋒從磨礪出,梅花香自苦寒來,作有溫度的攻城獅!本文由@IT·平頭哥聯盟-首席填坑官∙蘇南分享,@IT·平頭哥聯盟 主要分享前端、測試 等領域的積累,文章來源於(本身/羣友)工做中積累的經驗、填過的坑,但願能盡綿薄之力 助其餘同窗少走一些彎路
首席填坑官∙蘇南的專欄

做者:蘇南 - 首席填坑官

交流羣:912594095,公衆號:honeyBadger8

本文原創,著做權歸做者全部。商業轉載請聯繫@IT·平頭哥聯盟得到受權,非商業轉載請註明原連接及出處。

相關文章
相關標籤/搜索