我最近看到了一個純CSS實現的球體動畫效果:函數
通過研究上面的效果實現起來大體能夠分爲五個步驟,下面就來一一介紹。動畫
建立一個圓圈的第一步是生成全部組成圓圈的粒子。有了Jade,咱們不用一個一個的寫出200個div。spa
如下的代碼建立了一個容器.mommy和200個div:3d
.mommy - for (var x = 0; x < 200; x++) div
添加一點CSS確認一下200個div已經生成:code
.mommy{ border:1px solid black; } div{ width: 4px; height: 4px; background:red; }
正以下面你所看到的,咱們生成了一個800px高的紅色方塊,它是由200個div組成的。orm
接下來,咱們要將這200個div分別定位在不一樣的位置組成一個圓圈,並經過SCSS來實現。blog
在上面的CSS中還須要再添加一些設置,給全部的div設置絕對定位,並將它們向左和向上移動2px的距離,這樣div的中心點與容器的0,0座標點就重合了。而後,咱們設置容器爲固定的寬高大小。圖片
.mommy{ border:1px solid black; width: 400px; height: 400px; position: relative; } div{ width: 4px; height: 4px; background:red; position: absolute; top: -2px; left: -2px; }
經過SCSS,咱們能夠在for循環中爲每個div設置不一樣的位置,這樣就沒必要手動的一個一個去設置。首先建立一個變量,它的值等於div的個數,這樣在後面若是要用到div的數量值時,直接引用這個變量就能夠了。若是有一天須要改變成400個div,只須要在CSS中改變變量的值就能夠了。ip
$amount : 200; @for $i from 1 through $amount { //循環中的代碼 }
如今咱們就能夠在循環中改變每一個div的座標了,這須要一點點的數學計算。animation
如下的函數就是生成圓圈的座標點的計算公式:
x = cos((index/amount)*(PI*2))*radius + radius; y = sin((index/amount)*(PI*2))*radius + radius;
用SCSS來表示上面的公式就是:
$x : cos(($i/$amount)*360deg)*200px + 200; $y : sin(($i/$amount)*360deg)*200px + 200;
而後咱們將經過公式計算得出的點座標應用在每一個div上:
div:nth-child(#{$i}){ transform: translate3d($x, $y,0px); }
這是第一步生成的結果,雖然不是很漂亮,可是,嗯,你從零開始創造了一個圓圈!
如今咱們有了一個用SCSS生成的圓圈,可是咱們須要的是一個球體。圓圈是一個二維圖形,而球體是一個三維立體圖形。二維幾何圖形只有兩個軸:X軸和Y軸,而對於三維,又多了一個座標軸:Z軸。這意味着咱們還要計算每一個div在Z軸上的位置座標。幸運的是,已經有成熟的公式幫助咱們來定位球體上每一個元素的位置,我不會詳細的介紹公式的原理(屬於數學範疇),咱們只須要使用就能夠了:
θ : (index / amount) * 120; δ : (index / amount) * PI; x : radius * cos(δ) * cos(θ); y : radius * cos(δ) * sin(θ); z : radius * sin(δ);
如今咱們有了以上的函數,它能夠徹底知足咱們的需求,咱們把它插入到循環中。
@for $i from 1 through $amount { $theta : ($i / $amount) * 120; $delta : ($i / $amount) * pi(); $x : 200px * cos($delta) * cos($theta) + 200; //+200 to center our sphere in our 3D world $y : 200px * cos($delta) * sin($theta) + 200; //+200 to center our sphere in our 3D world $z : 200px * sin($delta); div:nth-child(#{$i}){ transform: translate3d($x, $y,$z); } }
下面就是生成的球體效果,正如你所看到的,全部的div都有從新有了新的位置,可是咱們看到的好像仍然是平面效果,不是3D立體的。
在CSS中有一個叫perspective的屬性,它容許咱們爲任何元素設置一個特定的透視值。在咱們的例子中,咱們但願在容器.mommy設置3D效果。而且還須要設置一個transform-style: preserve-3d;這樣全部的div就處於立體座標系中了。
如今咱們能夠看到全部div的大小都變得不同了。div距離「屏幕」的距離越遠,它就會越小,這意味着它們已經處於立體座標系中了!
全部的div已經就緒了,接下來咱們就要看到最後的結果了。咱們設置一個僅有一個關鍵幀的動畫效果:
.mommy{ [...] animation: rotation 10s linear infinite; } @keyframes rotation{ to{ transform:rotateY(360deg); } }
你可能已經注意到,有些div不是正面屏幕而是與屏幕成90°時,它們就會消失看不到。爲了防止這種狀況的發生,咱們須要給每一個div一個反方向的旋轉,讓它們的正面始終面對屏幕顯示。
咱們要在div上應用一個反方向的旋轉,可是因爲已經應用了一個轉換,咱們將利用僞元素,它將成爲紅色的小方塊。這樣,div自己只須要提供定位做用就能夠了,而且設置一個transform-style屬性,讓div處於3D環境中。
div{ [...] transform-style: preserve-3d; &:before{ content:""; display: block; width: 4px; height:4px; background:red; animation: rotation 10s infinite linear reverse; } }
塔達!CSS球體的效果就這樣作好了!
在以上代碼的基礎上,咱們發散思惟,能夠作出更加炫酷的球體效果:
獲取以上全部球體動畫的代碼能夠: