CSS3 3D transform

目錄

一、transform簡介

1、定義和用法

2、瀏覽器支持

3、語法

二、 學習步驟

1、 前情提要

2、 什麼是3D transform變換

3、 關鍵點:rotateX, rotateY, rotateZ

4、 perspective屬性

5、translateZ告訴你透視位置

6、perspective-origin

(1)源點向左偏

(2)源點左偏同時上偏

7、transform-style屬性

8、backface-visibility

(1)什麼是backface-visibility

(2)應用實例

①旋轉的甜甜圈

②灑落的咖啡

9、實際應用-CSS 3D開門動畫

一、transform簡介

1、定義和用法
transform 屬性對元素進行2D 或 3D 轉換。該屬性能讓我們對元素進行旋轉、縮放、移動或傾斜。

2、瀏覽器支持
在這裏插入圖片描述
(圖片來源於“菜鳥教程”)

3、語法
transform: none|transform-functions
在這裏插入圖片描述

(來源:W3School http://www.w3school.com.cn/cssref/pr_transform.asp)

學習步驟

1、前情提要

在這裏插入圖片描述

這是css3 中的3D座標系,後面會用的上

2、什麼是3D transform變換

CSS3中的3D變換效果,本質上就相當於我們在生活中做各種動作時姿勢體態的變換,又稱姿態的變換。

舉個栗子:

在這裏插入圖片描述

他們踢足球的過程就相當於在做3D變換!!!

所以,在現實生活中,一切的動作都屬於3D變換。

3、關鍵點:rotateX, rotateY, rotateZ

3D transform中有下面這三個方法:

rotateX( angle )
rotateY( angle )
rotateZ( angle )
這三個是學習和理解3D transform的基礎,也是弄懂perspective的突破口

rotateX( angle ):以x軸爲轉軸旋轉

在這裏插入圖片描述

rotateY( angle ):以y軸爲轉軸旋轉

在這裏插入圖片描述

rotateZ( angle ):以z軸爲轉軸旋轉

在這裏插入圖片描述

還不懂?!舉個栗子就知道了

在這裏插入圖片描述

郭偉陽在體操比賽中的運動是:rotateX

在這裏插入圖片描述

蔡依林的鋼管舞是:rotateY

在這裏插入圖片描述

這個運動員的運動就是:rotateZ

4、perspective屬性

perspective的中文意思是:透視,視角!

在這裏插入圖片描述

perspective:400px;

電腦顯示屏是一個2D平面,圖像之所以具有立體感(3D效果),其實只是一種視覺呈現,通過透視可以實現此目的。

透視可以將一個2D平面,在轉換的過程當中,呈現3D效果。
在這裏插入圖片描述

CSS3 3D transform的透視點是在瀏覽器的前方,相當於我們眼睛的位置

注:並非任何情況下需要透視效果,根據開發需要進行設置。

先來看看perspective的作用:

CSS代碼:

  .box{

            border:solid 1px #000;

            box-sizing:content-box;

            margin:100px auto;

            width:1000px;

            height:300px;

            /* 重點看這裏 */

            perspective:800px;

        }

        .child{

            box-sizing:content-box;

            width:300px;

            height:300px;

            float:left;

            margin-left:5px;

            background-color:#87D30A;

            /* 重點看這裏 */

            transform:rotateY(95deg);

        }

HTML代碼:

<div class="box">

        <div class="child"></div>

        <div class="child"></div>

        <div class="child"></div>

        <div style="clear:both;"></div>

    </div>

在這裏插入圖片描述

從這個demo看box父元素上有perspective,child子元素Y軸旋轉95度。從效果看可以想象這三個div的透視可以有一個交點,且這個交點看起來在第二個div附近。

接着,嘗試不斷調整perspective的值,從原來的800px調整到4000px,也就是原來的5倍。其他屬性不變,看看效果。

在這裏插入圖片描述

調整了perspective後你會發現div旋轉幅度變大了,且透視焦點轉移到了第一個div附近。通過這個調整發現,改變perspective的值透視焦點會發生改變。

在這裏插入圖片描述

這就是3D世界的座標圖。而perspective在Z軸上,而perspective是設置Z軸的長度。在css3中只有設置了perspective的值元素纔會有Z軸,perspective爲none元素則沒有Z軸(就是2D元素)。

5、translateZ告訴你透視位置
我們都知道近大遠小的道理,對於沒有rotateX以及rotateY的元素,translateZ的功能就是讓元素在自己的眼前或近或遠。

舉個栗子:

我們設置元素perspective爲201像素,如下:

perspective: 201px;

則其子元素,設置的translateZ值越小,則子元素大小越小(因爲元素遠去,我們眼睛看到的就會變小);

translateZ值越大,該元素也會越來越大,當translateZ值非常接近201像素,但是不超過201像素的時候(如200像素),該元素的大小就會撐滿整個屏幕(如果父輩元素沒有類似overflow:hidden的限制的話)。

因爲這個時候,子元素正好移到了你的眼睛前面,所謂“一葉蔽目,不見泰山”,就是這麼回事。當translateZ值再變大,超過201像素的時候,該元素看不見了——這很好理解:子元素已經移到透視點之後了,也就是移到眼睛的後面了,我們是看不見眼睛後面的東西的!

6、perspective-origin
perspective-origin屬性是3D變形中另一個重要屬性,主要用來決定perspective屬性的源點角度。它實際上設置了X軸和Y軸位置(或者說基點),在該位置觀看者好像在觀看該元素的子元素。

Pespective-origin: x-axis y-axis;

x-axis:

定義視圖在x軸上的位置。默認值:50%。可能的參數值形式:left、center、right、length和%。

y-axis:

定義視圖在y軸上的位置。默認值:50%。可能的參數值形式:top、center、bottom、length和%。

如果看了上面的介紹還是不太明白,沒有能在大腦中形成一個清晰的概念,那麼看下面這張截取的W3C官網的圖:

在這裏插入圖片描述

(圖片來源於:CSDN博主“我是新手”)

再來幾個代碼實慄就應該差不多懂了

(1)源點向左偏

.w1 {

perspective: 1000px;

}

.w2{

perspective: 1000px;

 perspective-origin: left center;

 }

.cube{

font-size: 4em;

width: 2em;

margin: 1.5em auto;

 transform-style: preserve-3d;

 }

在這裏插入圖片描述

源點左偏就相當於你正對這個正方體的時候,把頭往左偏,你的眼睛所看到的畫面,你的眼睛就相當於源點!

一個不夠?!再來個栗子

(2)源點左偏同時上偏

.w1 {

perspective: 1000px;

 } 

.w2{

perspective: 1000px;

perspective-origin: left -100px;

 }

在這裏插入圖片描述

現在知道了perspective-origin改變源點的作用了吧,把源點當做自己的眼睛,改變源點的位置,就相當於改變你眼睛的位置!

7、transform-style屬性
transform-style屬性是3D空間一個重要屬性,指定嵌套元素如何在3D空間中呈現。他主要有兩個屬性值:flat和preserve-3d

語法:transform-style: flat | preserve-3d

其中flat值爲默認值,表示所有子元素在2D平面呈現。preserve-3d表示所有子元素在3D空間中呈現。

如果對一個元素設置了transform-style的值爲flat,則該元素的所有子元素都將被平展到該元素的2D平面中進行呈現。沿着X軸或Y軸方向旋轉該元素將導致位於正或負Z軸位置的子元素顯示在該元素的平面上,而不是它的前面或者後面。如果對一個元素設置了transform-style的值爲preserve-3d,它表示不執行平展操作,他的所有子元素位於3D空間中。

注意:transform-style屬性需要設置在父元素中,並且高於任何嵌套的變形元素

是不是有點迷糊,沒事,咱舉個形象點的栗子

《喜羊羊與灰太狼》中的灰太狼都多多少少知道點吧,咱拿他來舉例

首先把灰太狼這個整體形象看做父元素,灰太狼的鼻子,耳朵,嘴等是子元素

第一種狀態:灰太狼被紅太狼一鍋拍在了衣服上(被拍成了扁平的)

在這裏插入圖片描述

現在就相當於灰太狼這個元素設置了transform-style,值爲flat,不管你沿X、Y軸怎麼轉, 鼻子、耳朵、嘴等都是與灰太狼這個整體在一個平面,你看到的也就只有一個扁平的灰太狼

第二種狀態:轉頭深情凝望
在這裏插入圖片描述

現在就相當於把transform-style的值設置爲preserve-3d

可以看到灰太狼轉頭後(相當於把灰太狼這個元素以Y軸爲軸心旋轉了),鼻子、耳朵、嘴等都不是在同一個平面上,而是滿滿的立體感

現在來點專業的解釋解釋吧

在這裏插入圖片描述

上圖的上部分:

當元素設置.rotate設置了flat值時,其子元素img不會根據translateZ()值攤開,而在同一平面旋轉;

上圖的下部分:

當元素.rotate設置了preserve-3d值時,其子元素img會根據translateZ()值攤開,不再會堆疊在一起。

注意:將元素的transform-style值設置爲preserve-3d,就不能爲了防止子元素溢出容器而將overflow值爲hidden,如果設置了overflow:hidden同樣可以迫使子元素出現在同一平面(和元素設置了transform-style爲flat一樣的效果)

8、backface-visibility
當你翻轉一個元素的時候,你看到的是什麼?通常情況下,我們應該看到的是元素的背面,這是正常的情況,但是有時候我們希望翻轉一個元素後看到的是另一個元素。通過backface-visibility:hidden;屬性,我們可以使一個元素在翻轉之後消失,這是可以使用另一個元素放在它的背面,從而製作出一種元素翻轉之後出現另一個元素的效果。

什麼是backface-visibility
backface-visibility屬性和3D transform效果相關,它用於決定當一個元素的背面面向用戶的時候是否可見。例如下面圖片展示的兩個圓形元素,前面一個是正面,後面一個是背面。當它翻轉到背面的時候,上面的文字應該是正面的鏡像,這是默認的行爲。

在這裏插入圖片描述

(以Y軸爲軸心)

(2)應用實例
①旋轉的甜甜圈

在這裏插入圖片描述

這個demo是理解backface-visibility屬性的很好的例子。

當我們翻轉了甜甜圈後,不希望再看到它的front面。因此我們需要另一幅代表甜圈背面的圖片來取代原來的背面。

我們會將"front"面和"back"main放置在相同的位置上,"front"面位於"back"面的前面。"front"面使用backface-visibility: hidden;來隱藏背面。它們會沿Y軸同步旋轉,轉動背面時,"front"面消失,另一幅圖片被展示出來。

關鍵代碼:

img {

  position: absolute;

  animation: turn 2s infinite;

}

  

.donut-front {

  z-index: 5;

  backface-visibility: hidden;

}

  

@keyframes turn {

  to {

    transform: rotateY(360deg);

  }

}          

兩張圖片都使用相同的動畫,只是第一張圖片在旋轉到背面時就被隱藏起來,這是第二張圖片就自然的展示出來。

②灑落的咖啡

在這裏插入圖片描述
(以Y軸爲軸心)

這個demo中有兩個咖啡杯圖片:一個是杯子的正面,一個杯子的背面。咖啡的水滴是一幅單獨的圖片,開始時它是隱藏的,它被在X軸上旋轉了180度,這使得我們開始時看到的是它的背面,又因爲設置了backface-visibility: hidden;,因此它是不可見的。

關鍵代碼:

img {

  position: absolute;

  animation: turn-over 2s 700ms infinite;

}

  

.cup-front {

  z-index: 3;

  backface-visibility: hidden;

}

  

.coffee-drip {

  position: absolute;

  transform: rotateX(180deg);

  backface-visibility: hidden;

  animation: spill 2s infinite;

  animation-delay: 700ms;

}

  

@keyframes turn-over {

  to {

    transform: rotateX(-180deg);

  }

}

  

@keyframes spill {

  to {

    transform: translateY(200px);

  }

}  

更多使用CSS3 backface-visibility屬性製作翻轉動畫效果

http://www.htmleaf.com/Demo/201504151687.html

實際應用-CSS 3D開門動畫
演示效果:

在這裏插入圖片描述
(開門3D效果,有聲音光線變化)

CSS代碼:@charset “utf-8”;

/* CSS Document */



.door-box {

    max-width: 100%;

    width: 375px;

height: 628px;

    margin: 40px auto;

    //background-color: #2a273c;

background-image: url(木紋地板.jpg);

    font-family: STHeiTi, SimHei;

    overflow: hidden;

    position: relative;

    z-index: 1;

}

.door-box.active {

    animation: flyIntoRoom 1s both;

}

.door-box div {

    position: absolute;

}

.wall {

    left: 0;

top: 0;

right: 0;

bottom: 46px;

    border-bottom: 3px solid #211820;

    background-color: #768bb6;

    max-height: calc(1.8 * (375px - 80px));

    margin: auto;

    box-shadow: 0 -200px #768bb6;

}

.door-border {

    top: 28px;

    left: 40px;

    right: 40px;

    bottom: 0;

    border: 3px solid #211820;

    border-radius: 2px 2px 0 0;

    border-bottom: 0;

    background-color: rgba(33,26,26,1.00);

}

.door-frame {

    top: 10px;

left: 9px;

right: 9px;

bottom: 0;

    border: 3px solid #211820;

    border-radius: 2px 2px 0 0;

    border-bottom: 0;

    background-image: url(臥室.jpg);

background-size: 200% 100%;

    -webkit-perspective: 1200px;

    perspective: 1200px;

}

.door {

    left: 0; top: 0; right: 0;  bottom: 0;

    -webkit-transform-style: preserve-3d;

    transform-style: preserve-3d;

    transform-origin: left;

    transform: rotateY(0deg);

    -webkit-backface-visibility: hidden;

    backface-visibility: hidden;

}

.door-face-1,

.door-face-0 {

    left: -3px; top: -3px; right: -3px; bottom: -3px;

    border: 3px solid rgba(33,26,26,1.00);

   

background-image: url(木門.jpg);

background-size: 100% 100%;

}

.door-face-0 {

    transform: translateZ(-12px);

}

.door-face-1 {

    transform: translateZ(0);

}

.door-face-2 {

    height: 6px;

    left: -3px; right: -3px; top: 0;

    border: 3px solid #211820;

    border-radius: 2px;

    background-color: rgba(33,26,26,1.00);

    transform: translate3D(0, -7.5px, -6px) rotateX(90deg);

}

.door-face-3 {

    width: 6px;

    top: -3px; right: 0;

bottom: -3px;

    border: 3px solid #211820;

    border-radius: 2px;

    background-color: rgba(33,26,26,1.00);

    transform: translate3D(7.5px, 0, -6px) rotateY(90deg);

}

/*光線*/

.light {

    left: 0; top: 0; bottom: 0;

    background:rgba(219,207,161,1);

    width: 1000px;

    transform: translateZ(-13px);

}

/*門牌*/

.door-card {

    width: 165px;

height: 60px;

    line-height: 60px;

    background-color:rgba(55,44,45,0.7);

    top: 60px;

left: 0;

right: 0;

    margin: auto;

    text-align: center;

    font-size: 30px;

    border: 3px solid;

    border-radius: 10px;

}

.door-btn {

    left: 0; right: 0;

    text-align: center;

    margin-top: 140px;

    font-size: 24px;

    color: #9dbce3;

    line-height: 36px;

}

.door-in {

    width: 104px; height: 40px;

    border-radius: 40px;

    border: 2px solid;

    line-height: 40px;

    background-color: #eacc86;

    font-family: inherit; font-size: 24px;

    padding: 0; margin: 10px 0;

}

/* 動畫 */

@keyframes flyIntoRoom {

    from {

        transform: scale(1) translateZ(0);

        opacity: 1;

    }

    to {

        transform: scale(2) translateZ(100px);

        opacity: 0;

    }

}

.room-img {

    position: absolute;

    width: 375px;

max-width: 100%;

    left: 0; right: 0;

top: 40px;

    margin: auto;

}

HTML代碼

<!doctype html>

<html>

<head>

<meta charset="utf-8">

<title>3D開門動畫</title>

<link href="style.css" rel="stylesheet" type="text/css">

</head>



<body>

<div id="doorBox" class="door-box">

    <div class="wall">

        <div class="door-border">

            <div class="door-frame">

                <!-- 門 -->

                <div id="door" class="door">

                    <!-- 門後的光線 -->

                    <div id="light" class="light" style="opacity: .8;" hidden=""></div>

                    <!-- 門後 -->

                    <div class="door-face-0"></div>

                    <!-- 三個面 -->

                    <div class="door-face-2"></div>            

                    <div class="door-face-1">

                        <!-- 門上的掛牌 -->

                        <div class="door-card">我的臥室</div>

                        <!-- 進入按鈕 -->

                        <div class="door-btn">

                            <button id="doorBtnIn" class="door-in">進入</button>

                        </div>

                    </div>

                    <div class="door-face-3"></div>

                </div>

            </div>

        </div>

    </div>

</div>

<!-- 書房 -->

<img src="木紋地板.jpg" class="room-img" width="375" height="500">

<div hidden><audio id="audioOpen" src="./open.mp3" preload></audio></div>



</body>



</html>

JS代碼:

<script>

// 門,光線這類運動元素

var eleDoor = document.getElementById('door');

var eleLight = document.getElementById('light');

var eleDoorBox = document.getElementById('doorBox');

// 開門音效mp3

var eleAudioOpen = document.getElementById('audioOpen');

// 開門動畫

var percentDoor = 0;

var fnOpenDoor = function () {

percentDoor++;

// 門完全打開後,進入下一個畫面

if (percentDoor == 100) {

//eleDoorBox.classList.add('active');

return;

}

// 門打開

eleDoor.style.transform = 'rotateY('+ (-90 * percentDoor / 100) +'deg)';

eleLight.removeAttribute('hidden');

// 光線變化

eleLight.style.opacity = 0.8 - 0.9 * percentDoor / 100;



setTimeout(fnOpenDoor, 16);

};

document.querySelector('#doorBtnIn').addEventListener('click', function () {

eleAudioOpen.play();

fnOpenDoor();

});

</script>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章