怎樣用CSS做出3D效果的雲
介紹
本文將介紹如何一步一步製作出一些3D效果的雲彩,會用到一些高階的屬性,主要是如何通過CSS的3D變換效果來實現,如果你想了解更多,這地方是個不錯的開始。
本教程將會分成幾個部分,每一部分都會有詳細的步驟讓你理解HTML,CSS和Javascript都是如何工作的,每一步都有銜接,以及一個連結來測試單個部分的程式碼效果。教程裡的程式碼是最終demo的簡化版,但是主要區別在每一部分都有說明。
- 1.新建一個世界和視角
- 2.向我們建立的世界裡新增物件
- 3.往我們的物件上新增層
- 4.讓3D效果執行起來
- 5.最後總結
1.新建一個世界和視角
首先,我們需要兩個div
元素: viewport
和 world
。剩下的部分將會在後面動態的加入。
viewport
包含了整一個螢幕和一個攝影機。由於在CSS 3D變換中沒有攝影機本身,就假想你在通過一個透明的玻璃螢幕來看螢幕裡的視野,你也可以改變看視野的方向。我們將會把所有物件都放在裡面,然後對他們進行變換。
world
是一個用來固定所有物件的 div
盒子。 旋轉,轉化或者放大都變換都會改變我們的元素。為簡單起見,我將在需要使用瀏覽器字首(-webkit,-moz,-0,-ms等等)的地方使用沒有字首的CSS屬性。
這就是我們需要的所有盒子模型:
<div id="viewport">
<div id = "world" ></div>
</div>
下面是我們定義的兩個CSS樣式,這裡非常重要的是要將 world
div 放在 viewport
div裡面,否則將無法渲染場景。要記住你將旋轉一個放置在文件裡的元素,像其他2D元素那樣。
#viewport{
bottom:0;
left:0;
overflow:hidden;
perspective:400;
position:absolute;
right:0;
top:0;
}
#world{
height: 512px;
left: 50%;
margin-left: -256px;
margin-top: -256px;
position: absolute;
top: 50%;
transform-style: preserve-3d;
width: 512px;
}
現在寫一些程式碼來初始化我們的物件,繫結 mousemove
事件以及定義 updateView()
函式。
/*
Defining our variables
world and viewport are DOM elements,
worldXAngle and worldYAngle are floats that hold the world rotations,
d is an int that defines the distance of the world from the camera
*/
var world = document.getElementById( 'world' ),
viewport = document.getElementById( 'viewport' ),
worldXAngle = 0,
worldYAngle = 0,
d = 0;
/*
Event listener to transform mouse position into angles
from -180 to 180 degress, both vertically and horizontally
*/
window.addEventListener( 'mousemove', function( e ) {
worldYAngle = -( .5 - ( e.clientX / window.innerWidth ) ) * 180;
worldXAngle = ( .5 - ( e.clientY / window.innerHeight ) ) * 180;
updateView();
} );
/*
Changes the transform property of world to be
translated in the Z axis by d pixels,
rotated in the X axis by worldXAngle degrees and
rotated in the Y axis by worldYAngle degrees.
*/
function updateView() {
world.style.transform = 'translateZ( ' + d + 'px ) \
rotateX( ' + worldXAngle + 'deg) \
rotateY( ' + worldYAngle + 'deg)';
}
world
是紅色的,viewport
有背景色來模擬天空,mousewheel
滾輪事件來監聽攝影機的遠近距離。移動滑鼠來觀察紅色的 div
是如何改變方向的。
2.向我們建立的世界裡新增物件
現在我們開始新增真正的3D內容。我們加入一些新的 div
放置在 world
空間裡。有必要新增幾個絕對位置的 div
作為 world
的子節點,但是用3D變換來替代 left
和 top
, 他們預設會出現在 world
的中央位置。width
和 height
屬性無關緊要,因為這些新的容器是放置那些真實雲的層。如果正式應用裡最好將他們居中(通過設定 margin-left
和 margin-top
屬性 來設定 width
和 height
一半的負數值)。
.cloudBase {
height: 20px;
left: 256px;
margin-left: -10px;
margin-top: -10px;
position: absolute;
top: 256px;
width: 20px;
}
我們新增 generate()
和 createCloud()
方法來充實 world
。注意 random_{var} 不是真實的變數值,而是一個程式碼佔位符,應該返回一個給定範圍內的隨機數。
/*
objects is an array of cloud bases
layers is an array of cloud layers
*/
var objects = [],
layers = [];
/*
Clears the DOM of previous clouds bases
and generates a new set of cloud bases
*/
function generate() {
objects = [];
layers = [];
if ( world.hasChildNodes() ) {
while ( world.childNodes.length >= 1 ) {
world.removeChild( world.firstChild );
}
}
for( var j = 0; j <; 5; j++ ) {
objects.push( createCloud() );
}
}
/*
Creates a single cloud base: a div in world
that is translated randomly into world space.
Each axis goes from -256 to 256 pixels.
*/
function createCloud() {
var div = document.createElement( 'div' );
div.className = 'cloudBase';
var t = 'translateX( ' + random_x + 'px ) \
translateY( ' + random_y + 'px ) \
translateZ( ' + random_z + 'px )';
div.style.transform = t;
world.appendChild( div );
return div;
}
頁面中那些粉紅色方塊的層就是雲層模型了,這裡有一個 p
變數來更簡單的改變 viewport.style.perspective
的值。試著去改變這個變數來觀察我們的攝影機是如何變化的。這個值越大,視角的垂直度就會越大。再次提醒,那個 randowm_{var} 並不是真正的變數。
3.往我們的物件上新增層
現在有趣的事情開始發生了,我們新增了幾個絕對位置的“雲層” div
盒子來表示雲,這些盒子將會用來裝載雲的貼圖。
.cloudLayer {
height: 256px;
left: 50%;
margin-left: -128px;
margin-top: -128px;
position: absolute;
top: 50%;
width: 256px;
}
舊的 createCloud()
函式做了一些改動,新增了雲層的隨機數。
/*
Creates a single cloud base and adds several cloud layers.
Each cloud layer has random position ( x, y, z ), rotation (a)
and rotation speed (s). layers[] keeps track of those divs.
*/
function createCloud() {
var div = document.createElement( 'div' );
div.className = 'cloudBase';
var t = 'translateX( ' + random_x + 'px ) \
translateY( ' + random_y + 'px ) \
translateZ( ' + random_z + 'px )';
div.style.transform = t;
world.appendChild( div );
for( var j = 0; j < 5 + Math.round( Math.random() * 10 ); j++ ) {
var cloud = document.createElement( 'div' );
cloud.className = 'cloudLayer';
cloud.data = {
x: random_x,
y: random_y,
z: random_z,
a: random_a,
s: random_s
};
var t = 'translateX( ' + random_x + 'px ) \
translateY( ' + random_y + 'px ) \
translateZ( ' + random_z + 'px ) \
rotateZ( ' + random_a + 'deg ) \
scale( ' + random_s + ' )';
cloud.style.transform = t;
div.appendChild( cloud );
layers.push( cloud );
}
return div;
}
雲層就是那些藍色帶有一點白色邊邊的部分,看起來相當有層次感吶。移動滑鼠來觀察下每一層的位置是怎樣的以及如何旋轉的。
4.讓3D效果執行起來
接下來就是見證奇蹟的時刻!我們用 layers[]
來為世界裡每一個單獨的雲層建立一個引用。我們用 worldXangle
和 worldYAngle
來表示整個空間的選擇變換。
如果我們將每個層都設定成相反的旋轉,這會在viewport裡重新調整他們:我們就有一個佈告板了。因為我們旋轉world先是X方向然後是Y方向,我們需要反著順序來旋轉每一個層,首先是Y方向再是X方向,變換的順序是非常重要的,如果你沒有正確的設定順序,元素的方向就都會不對了。
/*
Iterate layers[], update the rotation and apply the
inverse transformation currently applied to the world.
Notice the order in which rotations are applied.
*/
function update (){
for( var j = 0; j < layers.length; j++ ) {
var layer = layers[ j ];
layer.data.a += layer.data.speed;
var t = 'translateX( ' + layer.data.x + 'px ) \
translateY( ' + layer.data.y + 'px ) \
translateZ( ' + layer.data.z + 'px ) \
rotateY( ' + ( - worldYAngle ) + 'deg ) \
rotateX( ' + ( - worldXAngle ) + 'deg ) \
scale( ' + layer.data.s + ')';
layer.style.transform = t;
}
requestAnimationFrame( update );
}
來回的移動滑鼠,你將會看到藍色的雲層現在已經變成垂直的了(他們總是面對這鏡頭),但是 world
和其他雲基體還是三維空間裡的物件。
最後總結
為了達到最後的效果,只需要將用來除錯的那些顏色去掉,把雲層 div
用一個 img
貼上雲的圖片。注意圖片得是帶有alpha通道的PNG格式,要不沒效果。
當然,你可以隨意換其他你想要的圖片:煙霧痕跡,等離子體雲,綠葉,飛行的麵包機等等。只要把 backgroud-image
更改下就好了。混合不同比例的紋理材質會有神奇的效果。
隨機的新增元素是可以的,但是你也可以建立有序的結構,比如樹,鴨子形狀的雲或者複雜的大爆炸等。可以嘗試一些3D曲線,建立固定的雲的執行軌跡,創造一個多人遊戲來猜3D雲的形狀等等,充滿著無限可能。
NOTE:文中的程式碼都是簡化了的哦,如果想一步一步實際操作的話最好儲存下示例效果的連結頁面來檢視原始碼。
本文譯自 https://www.clicktorelease.com/blog/how-to-make-clouds-with-css-3d#
相關文章
- CSS能做出的效果CSS
- ui設計怎樣做出有效果的視覺層級?UI視覺
- CSS 3D旋轉效果CSS3D
- CSS3實現的3D旋轉效果CSSS33D
- 怎樣在PowerPoint製作3D動態幻燈片效果3D
- CSS3實現3D魔方效果CSSS33D
- 3D 穿梭效果?使用 CSS 輕鬆搞定3DCSS
- CSS3實現3D翻牌效果CSSS33D
- CSS3 3d旋轉魔方效果CSSS33D
- 全員養貓的遊戲公司,會做出怎樣的遊戲?遊戲
- CSS 怎樣寫一個動畫(從基礎動畫到3d動畫)CSS動畫3D
- css3 3D 深度翻轉效果案例CSSS33D
- CSS3實現3d效果照片牆CSSS33D
- CSS3多面體3D運動效果CSSS33D
- CSS3 3D方塊效果程式碼CSSS33D
- 怎樣為 CSS 命名?CSS
- CSS3實現多樣的邊框效果CSSS3
- CURD系統怎麼做出技術含量--怎樣引導面試面試
- css3實現的3D立體旋轉效果CSSS33D
- css3實現的立方體3D旋轉效果CSSS33D
- css樣式背景顏色漸變效果CSS
- CSS3立方體3D旋轉效果CSSS33D
- 文字的3D效果3D
- css3帶你實現3D轉換效果CSSS33D
- 如何製作室內地圖?停車場效果圖怎麼做出來的?地圖
- 怎樣用純HTML和CSS更改預設的上傳檔案按鈕樣式HTMLCSS
- 用css實現視差效果CSS
- 怎樣用原生js配合css的transition寫個無縫滾動JSCSS
- 學習 canvas 的 globalCompositeOperation 做出的神奇效果Canvas
- 基於 HTML5 Canvas 的 3D 熱力雲圖效果HTMLCanvas3D
- jq怎麼寫css樣式CSS
- 如何用JavaScript做出淘寶評星效果JavaScript
- 電話機器人的使用效果怎麼樣?機器人
- CSS3動畫實現3D倒數計時效果CSSS3動畫3D
- 使用CSS3實現3D圖片滑塊效果CSSS33D
- 使用 three.js 中的 CSS3DRenderer 實現 3d 卡片的效果JSCSSS33D
- 怎麼實現一個3d翻書效果3D
- 用純 CSS 實現鏤空效果CSS