寫這篇文章的原因是由於看到了這個頁面:css
運用 CSS3 完成的 3D 視角,雖然有一些暈3D,可是令人置身於其中的交互體驗感受很是棒,運用在移動端製做一些 H5 頁面可謂十分博人眼球。git
而且掌握原理以後製做起來也並不算廢力,好好的研究了一番後將一些學習過程共享給你們。github
下面進入正文:(一些 Gif 圖片較大,須要等待一會)app
百聞不如一見,先直觀感覺一下上述我所說的效果:ide
最好能點進去看看,這裏我使用了帶背景色的 div 做爲示例,咱們的視角處於一個正方體中,正方體的旋轉動畫讓咱們有了 3D 的感受。函數
那麼本來的圖長什麼樣呢?咱們把距離拉遠,一探究竟:佈局
是長這樣的:學習
相較於第一種效果,其實所作的只是將咱們的視角推動到了正方體當中,有了一種身臨其景的感受。動畫
而合理的運用 CSS3 所提供的一些 3D 屬性,很容易就能達到上述的效果。
製做這樣一個 3D 圖形,我在以前的文章已經很詳細的講述了過程,感興趣的能夠戳進去看看:
再簡單複述一下,主要是運用到了兩個 CSS 屬性:
要利用 CSS3 實現 3D 的效果,最主要的就是藉助 transform-style 屬性。
transform-style 只有兩個值能夠選擇:
// 語法: transform-style: flat|preserve-3d; transform-style: flat; // 默認,子元素將不保留其 3D 位置 transform-style: preserve-3d; // 子元素將保留其 3D 位置。
當父元素設置了 transform-style:preserve-3d 後,就能夠對子元素進行 3D 變形操做了,3D 變形和 2D 變形同樣能夠,使用 transform 屬性來設置,或者能夠經過制定的函數或者經過三維矩陣來對元素變型操做:當咱們指定一個容器的 transform-style 的屬性值爲 preserve-3d 時,容器的後代元素便會具備 3D 效果,這樣說有點抽象,也就是當前父容器設置了 preserve-3d 值後,它的子元素就能夠相對於父元素所在的平面,進行 3D 變形操做。
使用 translateX(length) 、translateY(length) 、 translateZ(length) 來進行 3D 位移操做,與 2D 操做同樣,對元素進行位移操做,也能夠合併爲 translate3d(x,y,z) 這種寫法;
使用 scaleX() 、scaleY() 、scaleY() 來進行3D 縮放操做,也能夠合併爲 scale3d(number,number,number) 這種寫法;
使用 rotateX(angle) 、rotateY(angle) 、rotateZ(angle) 來進行 3D 旋轉操做,也能夠合併爲 rotate3d(Xangle,Yangle,Zangle) 這種寫法。
// 語法 perspective: number|none;
簡單來講,當元素沒有設置 perspective 時,也就是當 perspective:none/0 時全部後代元素被壓縮在同一個二維平面上,不存在景深的效果。perspective 爲一個元素設置三維透視的距離,僅做用於元素的後代,而不是其元素自己。
而若是設置 perspective 後,將會看到三維的效果。
咱們上面之因此可以在正方體外圍看到正方體,以及深刻正方體內,都是由於 perspective
這個屬性。它讓咱們可以選擇推動視角,仍是遠離視角,所以便有了 3D 的感受。
爲了完成這樣一個效果,須要一個靈活的佈局,去控制整個 3D 效果的展現。
下面是我以爲比較好的一種方式:
<!-- 最外層容器,控制圖形的位置及在整個頁面上的佈局--> <div class="container"> <!-- 舞臺層,設置 preserve-3d 與 perspective 視距 --> <div class="stage"> <!-- 控制層,動畫的控制層,經過這一層能夠添加旋轉動畫或者觸摸動畫 --> <div class="control"> <!-- 圖片層,裝入咱們要拼接的圖片 --> <div class="imgWrap"> <div class="img img1"></div> <div class="img img2"></div> <div class="img img3"></div> <div class="img img4"></div> </div> </div> </div> </div>
container
,控制圖形的位置及在整個頁面上的佈局;stage
層,舞臺層,從這裏開始設置 3D 景深效果,添加 perspective 視距;control
層,動畫的控制層,經過這一層能夠添加旋轉動畫或者在移動端的觸摸動畫,經過更改translateZ
屬性也能夠拉近拉遠視角;imgWrap
層,圖片層,裝入咱們要拼接的圖片,下文會說起。圖片拼接其實才是個技術活,須要許多的計算。
以上述 Demo 中的正方體爲例子,class 爲 img
的 div 塊的高寬爲 400px*400px。那麼要利用 4 個 這樣的 div 拼接成一個正方體,須要分別將 4 個 div 繞 Y 軸旋轉 [90°, 180°, 270°, 360°],再 translateY(200px)
。
值得注意的是,必定是先旋轉角度,再偏移距離,這個順序很重要。
看看俯視圖,也就是這個意思:
這是最簡單的狀況了,都是直角。
若是是一張圖須要分割成八份,假設每張圖分割出來的高寬爲 400 400 , 8 張圖須要作的操做是依次繞 Y 軸旋轉 [45°, 90°, 135°, 180°, 225°, 270°, 315°, 360°] ,偏移的距離爲 translateY(482.84px)
,也就是 (200 + 200√2)。
看看俯視圖:
效果圖:
上面的示例都是使用的帶背景色的 div 塊,如今咱們選取一張真正的圖片,將其拼接成一個柱體。
下面這張圖,大小爲 3480px * 2000px
:
咱們把它分割爲 20 份,拼成一個正 20 邊形,固然不用一塊一塊切圖下來,利用 background-position
就能夠完成了。並且分割的份數越多,最終作出來的效果越像一個圓柱,效果也更加真實。
正 20 邊形,須要 20 個 div ,假設容器是 .img-bg1 ~ .img-bg20 ,那麼每塊圖片的寬度爲 174px
,依次須要遞增的角度爲 18° ,而且咱們須要計算出須要偏移的距離爲 translateZ(543px)
。
能夠利用一些 CSS 預處理器處理這段代碼,下面是 Sass 的寫法:
// Sass 的寫法 $imgCount : 20 !default; @for $i from 1 through $imgCount { .img-bg#{$i}{ background-position:($i * -174px + 174px) 0; transform: rotateY($i * 18deg) translateZ(543px); } }
看看效果: Demo能夠戳這裏
能夠看到,圖中近視爲一個圓柱形,不過有一些小問題:
control
層,進入到圓柱畫面內作到這一步,只剩下最後一步,就是推動咱們的視角,進入到圓柱內部,產生 3D 視圖的感受。
咱們經過 class 爲 control
這個 div 控制這個效果,不過這裏控制咱們進入圓柱內部的屬性不是調整修改 perspective
屬性,而是調整 translateZ
屬性。經過控制 translateZ 獲得的畫面更加真實,能夠本身嘗試一下分別控制 perspective
與 translateZ
獲得的效果,便會有深入的感覺。
最後的效果: Demo能夠戳這裏,因爲是移動端效果,打開模擬器觀看更佳
整個效果圖太大,只截取了部分製做成 GIF:
還有一個小問題,那就是進入到圓柱內部以後,整個圖片都反了過來,因此咱們可能須要利用PS將原圖進行一次左右翻轉,這樣進入內部以後,看到的就是原圖效果。
至此,整個頁面就算完工了,接下來的就是添加一些 touch 事件,增添一些細節。可能寫的過程當中遺漏了一些細節,有什麼很難一下理解過來的地方能夠在評論留言。
本文示例 Demo 已上傳在個人 Github 上:
到此本文結束,若是還有什麼疑問或者建議,能夠多多交流,原創文章,文筆有限,才疏學淺,文中如有不正之處,萬望告知。