CSS觀點如何工作
CSS動畫愛好者經常會用到透視(perspective)這個強大的工具。雖然透視屬性本身無法實現3D效果(因為基本形狀沒有深度),但您可以使用transform
屬性在3D空間(X、Y和Z軸)移動和旋轉對象,然後使用透視來控制深度。
本文將從基礎知識開始,逐步講解透視的概念,最終創建一個完整的3D旋轉立方體動畫。
透視基礎
我們從一個簡單的綠色正方形開始,並在三個軸上移動它。
在X和Y軸上移動對象非常簡單,但如果在Z軸上移動它,看起來正方形保持不變。這是因為當對像在Z軸上移動時,動畫使它靠近我們,然後遠離我們,但正方形的大小(和位置)保持不變。這就是CSS perspective
屬性發揮作用的地方。
雖然透視在對像在X或Y軸上移動時沒有影響,但當對像在Z軸上移動時,透視使正方形在靠近我們時看起來更大,在遠離我們時看起來更小。是的,就像在現實生活中一樣。
同樣的效果也發生在我們旋轉對象時:
在Z軸上旋轉正方形看起來像是我們都熟悉和喜愛的常規旋轉,但是當我們在X或Y軸上旋轉正方形(不使用透視)時,它看起來只是正方形變小(或變窄)而不是旋轉。但是當我們添加透視時,我們可以看到當正方形旋轉時,正方形的近側看起來更大,遠側看起來更小,旋轉看起來符合預期。
請注意,當對像在X或Y軸上的旋轉角度為90°(或270°、450°、630°等)時,它將“消失”在視野之外。同樣,這是因為我們無法向對象添加深度,在這個位置,正方形的寬度(或高度)實際上將為0。
透視值
我們需要使用一個值來設置perspective
屬性。此值設置對象平面的距離,或者換句話說,透視的強度。值越大,您離對象越遠;值越小,透視效果越明顯。
透視原點
perspective-origin
屬性確定您“觀察”對象的方位。如果原點居中(這是默認值)並且對象向右移動,則看起來您是從左側觀察它(反之亦然)。
或者,您可以將對象居中並移動perspective-origin
。當原點設置為側面時,就像您從該側面“觀察”對像一樣。值越大,看起來越偏離中心。
變換
雖然perspective
和perspective-origin
都設置在元素的父容器上,並確定消失點的位置(即從您“觀察”對象的位置到對象平面的距離),但對象的位移和旋轉是使用transform
屬性設置的,該屬性在對象本身上聲明。
如果您查看前面示例的代碼,我將正方形從一側移動到另一側,您會看到我使用了translateX()
函數——這是有道理的,因為我想讓它沿X軸移動。但是請注意,它被分配給transform
屬性。該函數是一種直接應用於我們要轉換的元素的變換類型,但其行為符合分配給父元素的透視規則。
我們可以將多個函數“鏈接”到transform
屬性。但是當使用多個變換時,需要考慮三件非常重要的事情:
- 旋轉對象時,其坐標系會隨著對像一起變換。
- 平移對象時,它相對於自身的坐標系移動(而不是其父坐標)。
- 這些值的書寫順序會(並且會)改變最終結果。
為了獲得我在前面演示中想要的效果,我首先需要在X軸上平移正方形。只有這樣我才能旋轉它。如果這樣做順序顛倒(先旋轉,然後平移),則結果將完全不同。
為了強調值順序對transform
屬性的重要性,讓我們來看幾個簡單的例子。首先,是對兩個正方形的簡單二維(2D)變換,這兩個正方形都具有相同的變換值,但聲明順序不同:
即使我們在Y軸上旋轉正方形,情況也是一樣的:
需要注意的是,雖然值的順序很重要,但我們可以簡單地更改值本身來獲得所需的結果,而不是更改值的順序。例如……
<code>transform: translateX(100px) rotateY(90deg);</code>
……與以下效果相同:
<code>transform: rotateY(90deg) translateZ(100px);</code>
這是因為在第一行中,我們在旋轉對象之前在X軸上移動了對象,但在第二行中,我們旋轉了對象,更改了其坐標,然後在Z軸上移動了它。相同的結果,不同的值。
讓我們看看更有趣的東西
當然,正方形是解釋透視一般概念的好方法,但是當我們分解成三維(3D)形狀時,我們才能真正看到透視是如何工作的。
讓我們使用到目前為止我們已經介紹的所有內容來構建一個3D立方體。
HTML
我們將創建一個.container
元素,它圍繞一個.cube
元素,而.cube
元素又包含六個元素,代表立方體的六個面。
<div class="container"> <div class="cube"> <div class="side front"></div> <div class="side back"></div> <div class="side left"></div> <div class="side right"></div> <div class="side top"></div> <div class="side bottom"></div> </div> </div>
通用CSS
首先,我們將向父.container
元素添加一些透視。然後,我們將確保.cube
元素具有200px的邊長並遵守3D變換。我在這裡添加了一些表現性樣式,但關鍵屬性已突出顯示。
/* 父容器,具有透視*/ .container { width: 400px; height: 400px; border: 2px solid white; border-radius: 4px; display: flex; justify-content: center; align-items: center; perspective: 800px; perspective-origin: top right; } /* 子元素,保留3D變換*/ .cube { position: relative; width: 200px; height: 200px; transform-style: preserve-3d; } /* 立方體的面,絕對定位*/ .side { position: absolute; width: 100%; height: 100%; opacity: 0.9; border: 2px solid white; } /* 立方體面的背景顏色,有助於可視化工作*/ .front { background-color: #d50000; } .back { background-color: #aa00ff; } .left { background-color: #304ffe; } .right { background-color: #0091ea; } .top { background-color: #00bfa5; } .bottom { background-color: #64dd17; }
變換面
正面是最簡單的。我們將它向前移動100px:
.front { background-color: #d50000; transform: translateZ(100px); }
我們可以通過添加translateZ(-100px)
將立方體的背面向後移動。另一種方法是旋轉側面180deg,然後向前移動:
.back { background-color: #aa00ff; transform: translateZ(-100px); /* or */ /* transform: rotateY(180deg) translateZ(100px); */ }
像背面一樣,我們可以通過幾種方法來變換左右側:
.left { background-color: #304ffe; transform: rotateY(90deg) translateZ(100px); /* or */ /* transform: translateX(100px) rotateY(90deg); */ } .right { background-color: #0091ea; transform: rotateY(-90deg) translateZ(100px); /* or */ /* transform: translateX(-100px) rotateY(90deg); */ }
頂部和底部略有不同。我們不需要在Y軸上旋轉它們,而需要在X軸上旋轉它們。同樣,它可以通過幾種不同的方式完成:
.top { background-color: #00Bfa5; transform: rotateX(90deg) translateZ(100px); /* or */ /* transform: translateY(-100px) rotateX(90deg); */ } .bottom { background-color: #64dd17; transform: rotateX(-90deg) translateZ(100px); /* or */ /* transform: translateY(100px) rotateX(90deg); */ }
這就得到了一個3D立方體!
隨意嘗試不同的perspective
和perspective-origin
選項,看看它們如何影響立方體。沒有一個“正確”的值,這些值因項目而異,因為它們取決於動畫、對象的大小以及您想要實現的效果。
讓我們談談transform-style
我們將向立方體添加一些精美的動畫,但是讓我們首先討論transform-style
屬性。我之前在通用CSS中添加了它,但並沒有真正解釋它是什麼或它做什麼。
transform-style
屬性有兩個值:
-
flat
(默認值) -
preserve-3d
當我們將屬性設置為preserve-3d
時,它會做兩件重要的事情:
- 它告訴立方體的面(子元素)與立方體位於相同的3D空間中。如果未將其設置為
preserve-3d
,則默認值為flat
,並且面在立方體的平面上被展平。preserve-3d
將立方體的透視“複製”到其子元素(面),並允許我們僅旋轉立方體,因此我們不需要分別為每個面設置動畫。 - 它根據子元素在3D空間中的位置顯示它們,而不管它們在DOM中的位置如何。
此示例中有三個正方形——綠色、紅色和藍色。綠色正方形的translateZ
值為100px,這意味著它位於其他正方形的前面。藍色正方形的translateZ
值為-100px,這意味著它位於其他正方形的後面。
但在DOM中,正方形的順序是:綠色、紅色、藍色。因此,當transform-style
設置為flat
(或根本未設置)時,藍色正方形將顯示在頂部,綠色正方形將在後面,因為這是DOM的順序。但是,如果我們將transform-style
設置為preserve-3d
,它將根據其在3D空間中的位置進行渲染。結果,綠色正方形將在前面,藍色正方形將在後面。
動畫
現在,讓我們為立方體設置動畫!為了使事情更有趣,我們將動畫添加到所有三個軸。首先,我們將animation
屬性添加到.cube
。它現在還不會做任何事情,因為我們還沒有定義動畫關鍵幀,但是當我們這樣做時,它已經到位了。
animation: cubeRotate 10s linear infinite;
現在是關鍵幀。我們基本上要沿每個軸旋轉立方體,使其看起來像在空間中滾動。
@keyframes cubeRotate { from { transform: rotateY(0deg) rotateX(720deg) rotateZ(0deg); } to { transform: rotateY(360deg) rotateX(0deg) rotateZ(360deg); } }
perspective
屬性實際上是賦予動畫深度的屬性,就像我們看到立方體向左和向右滾動,以及向前和向後滾動一樣。
但是在此之前, perspective
屬性的值是一致的, perspective-origin
也是如此。讓我們看看更改這些值如何影響立方體的外觀。
我已在此示例中添加了三個滑塊,以幫助查看不同的值如何影響立方體的透視:
-
左側滑塊設置
perspective
屬性的值。記住,此值設置對象平面的距離,因此值越小,透視效果越明顯。 -
另外兩個滑塊指的是
perspective-origin
屬性。右側滑塊在垂直軸上設置原點,從上到下,底部滑塊在水平軸上設置原點,從右到左。
請注意,在動畫運行時,這些變化可能不太明顯,因為立方體本身在旋轉,但是您可以通過單擊“運行動畫”按鈕輕鬆關閉動畫。
隨意嘗試這些值,並了解它們如何影響立方體的外觀。沒有一個“正確”的值,這些值因項目而異,因為它們取決於動畫、對象的大小以及您想要實現的效果。
接下來的步驟?
既然您已經掌握了CSS中perspective
屬性的基礎知識,您可以發揮您的想像力和創造力,在您自己的項目中創建3D對象,為您的按鈕、菜單、輸入和其他任何您想要“賦予生命”的東西添加深度和趣味。
同時,您可以嘗試創建一些複雜的結構和基於透視的動畫來練習和提高您的技能,例如這個、這個、這個,甚至這個。
我希望您喜歡閱讀這篇文章並在過程中學習到一些新東西!隨意留下評論,讓我知道您的想法,或者如果您對本文中的透視或任何其他主題有任何疑問,請在Twitter上給我留言。
以上是CSS觀點如何工作的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

您是否曾經在項目上需要一個倒計時計時器?對於這樣的東西,可以自然訪問插件,但實際上更多

關於Flex佈局中紫色斜線區域的疑問在使用Flex佈局時,你可能會遇到一些令人困惑的現象,比如在開發者工具(d...

在元素個數不固定的情況下如何通過CSS選擇第一個指定類名的子元素在處理HTML結構時,常常會遇到元素個數不�...
