摘要:參考環(huán)形路徑平移的方案,做一些調(diào)整,就可以得到型路徑平移的寫法這里初始把元素放在了上面那個(gè)半圓環(huán)的圓心,然后在的關(guān)鍵幀位置切換為下面的半圓環(huán)路徑。
最近在CSS Secrets一書看到了這樣一節(jié):讓一個(gè)元素沿環(huán)形路徑平移。這是一個(gè)css動畫的問題,但卻沒有看上去那么簡單,其關(guān)鍵點(diǎn)是元素是平移的,也就是說,元素自身并不發(fā)生旋轉(zhuǎn),只是穩(wěn)定地沿著一個(gè)環(huán)形的路徑移動,像這樣:
在書中作者Lea Verou已經(jīng)給出了解答(實(shí)際上,可以追溯到作者更早的這篇博文),不過,我認(rèn)為再補(bǔ)充一點(diǎn)周邊細(xì)節(jié)知識可能會更易于理解。因此,本文整理了一些東西,將嘗試更詳細(xì)地解答這個(gè)問題。
從旋轉(zhuǎn)動畫開始最開始看到這個(gè)問題的時(shí)候,會很容易想到用transform-origin定義圓心的位置,然后用rotate()進(jìn)行旋轉(zhuǎn)。css代碼大概是這樣(半徑為150px):
@keyframes spin { to { transform: rotate(1turn); } } .avatar{ animation: spin 10s infinite linear; transform-origin: 50% 150px; }
搭配的html很簡單:
對應(yīng)的效果是:
可以看到,這是一個(gè)旋轉(zhuǎn)動畫,元素在沿著環(huán)形路徑移動的同時(shí),自身也會圍繞圓心發(fā)生旋轉(zhuǎn)。因此,這并不是我們想要的平移效果。
但另一方面,元素沿環(huán)形路徑移動這一點(diǎn)是符合我們的目標(biāo)的。所以,可以在這個(gè)基礎(chǔ)上思考如何改進(jìn)。
利用多元素的變形相消w3c的The Transform Function Lists里提到:
If a list of
is provided, then the net effect is as if each transform function had been specified separately in the order provided.
意思是,當(dāng)一個(gè)元素的transform添加了多個(gè)變換函數(shù)時(shí),其效果等同于按照這些變換函數(shù)的順序依次分散添加在多層元素中。例如,以下元素:
其變換結(jié)果等效于:
這是一條非常有用的規(guī)則?,F(xiàn)在,假如有一個(gè)應(yīng)用了旋轉(zhuǎn)變換函數(shù)的元素是:
顯然,這個(gè)元素其實(shí)是沒有旋轉(zhuǎn)的,因?yàn)閮蓚€(gè)旋轉(zhuǎn)變換函數(shù)剛好抵消。這時(shí)候,我們再用一下前面的規(guī)則,就知道它等同于:
也就是說,內(nèi)層元素可以通過變形來抵消外層的變形效果。
現(xiàn)在回到旋轉(zhuǎn)動畫,既然元素已經(jīng)是沿環(huán)形路徑移動了,我們要做的就是抵消掉元素自身的旋轉(zhuǎn)。參考上面的原理,我們可以增加一個(gè)容器元素:
然后為它們搭配不同的動畫:
@keyframes spin { to { transform: rotate(1turn); } } @keyframes spin-reverse { from { transform: rotate(1turn); } } .avatar { animation: spin 10s infinite linear; transform-origin: 50% 150px; } .avatar > img { animation: spin-reverse 10s infinite linear; }
這段代碼把旋轉(zhuǎn)動畫搬到了div.avatar這個(gè)容器元素上,然后為
對應(yīng)的css:
@keyframes spin { from { transform: translate(50%, 150px) rotate(0turn) translate(-50%, -150px) translate(50%, 50%) rotate(1turn) translate(-50%, -50%); } to { transform: translate(50%, 150px) rotate(1turn) translate(-50%, -150px) translate(50%, 50%) rotate(0turn) translate(-50%, -50%); } } .avatar { animation: spin 10s infinite linear; }
上面的代碼特意把transform的值分成兩行,分別代表原來的兩個(gè)元素各自的變換函數(shù)。到此,這段代碼就已經(jīng)可以讓單個(gè)元素達(dá)成前文的兩個(gè)元素的效果了。不過,這段代碼還比較冗長,可以再做一點(diǎn)簡化。
我們很清楚transform的變換函數(shù)的順序很重要,不能隨意交換,但相鄰的同類變換函數(shù)可以考慮合并。
首先,可以找到位于中間的translate(-50%, -150px)和translate(50%, 50%)可以合并,得到translateY(-150px) translateY(50%)(百分比和像素值則不能再合并)。
然后,以from的部分為例,注意rotate(0turn)和rotate(1turn)分別來自原來的兩個(gè)元素,它們的角度值是為了互相抵消準(zhǔn)備的,因此必須和為360deg(1turn = 360deg):其中一個(gè)的角度值為x,另一個(gè)則為360 - x。
也就是說,元素在rotate(0turn)之前(未發(fā)生旋轉(zhuǎn)),和rotate(1turn)之后(發(fā)生了兩次旋轉(zhuǎn)),元素的角度是一致的(合計(jì)剛好轉(zhuǎn)了360deg),此時(shí)發(fā)生的translate()也可以合并。以此找到最前的translate(50%, 150px)和最后的translate(-50%, -50%),它們可以合并,得到translateY(150px) translateY(-50%)。
至此,代碼變?yōu)椋?/p>
@keyframes spin { from { transform: translateY(150px) translateY(-50%) rotate(0turn) translateY(-150px) translateY(50%) rotate(1turn); } to { transform: translateY(150px) translateY(-50%) rotate(1turn) translateY(-150px) translateY(50%) rotate(0turn); } } .avatar { animation: spin 10s infinite linear; }
代碼雖然看起來沒怎么變短,但變換函數(shù)更細(xì)致明確了。最后,注意最開始的兩個(gè)translateY(),它們在from和to里都是一樣的,因此,完全可以在動畫之外,一開始就把元素放在那個(gè)位置,從而消除這兩個(gè)translateY()。
實(shí)際上,這兩個(gè)translateY()的位移做的事就是把這個(gè)元素放到環(huán)形路徑的圓心。
這樣,代碼再變?yōu)椋?/p>
@keyframes spin { from { transform: rotate(0turn) translateY(-150px) translateY(50%) rotate(1turn); } to { transform: rotate(1turn) translateY(-150px) translateY(50%) rotate(0turn); } } .avatar { animation: spin 10s infinite linear; }
這就是精簡后的單元素環(huán)形路徑平移的解決方案了。代碼直觀看上去,可能會覺得比較難理解,畢竟它是我們經(jīng)過前面這樣一大段的分析推理得到的。
盡管如此,也有一篇文章介紹了如何直接理解這段環(huán)形路徑平移的代碼,推薦有興趣的你看看。
一點(diǎn)額外的嘗試 螺旋路徑平移在環(huán)形平移路徑的代碼的基礎(chǔ)上,改變起點(diǎn)或終點(diǎn)的圓環(huán)半徑,可以得到螺旋路徑:
@keyframes spin { from { transform: rotate(0turn) translateY(-150px) translateY(50%) rotate(2turn); } to { transform: rotate(2turn) translateY(-50px) translateY(50%) rotate(0turn); } }
對應(yīng)的效果:
這里為了體現(xiàn)螺旋效果,把圈數(shù)增加到了2圈。
S形路徑把兩個(gè)環(huán)形各取一半拼在一起,就可以得到S型路徑。參考環(huán)形路徑平移的方案,做一些調(diào)整,就可以得到S型路徑平移的寫法:
@keyframes spin{ 0%{ transform: rotate(-90deg) translateX(50px) rotate(90deg);} 49.9%{ transform: rotate(-270deg) translateX(50px) rotate(270deg);} 50.0% { transform: translateY(100px) rotate(-90deg) translateX(50px) rotate(90deg);} 100% { transform: translateY(100px) rotate(90deg) translateX(50px) rotate(-90deg);} }
這里初始把元素放在了上面那個(gè)半圓環(huán)的圓心,然后在50.0%的關(guān)鍵幀位置切換為下面的半圓環(huán)路徑。由于這個(gè)切換過程會讓元素小小地停滯一下,并不是我們想要的動畫,所以這里用帶小數(shù)的關(guān)鍵幀位置來盡可能縮短它的時(shí)長,使整個(gè)動畫更平滑。最終效果是:
一點(diǎn)補(bǔ)充matrix()是transform里一個(gè)特殊的變換函數(shù),它可以通過矩陣乘法把rotate()、translate()等其他變換函數(shù)全部合并在一起。但是,matrix()并不能簡化本文的動畫代碼,因?yàn)閏ss動畫將無法確認(rèn)如何生成關(guān)鍵幀之間的補(bǔ)間動畫,如果關(guān)鍵幀里只有一個(gè)合并后的matrix(),css動畫只會按照平鋪的方式去完成過渡。
以文章最開始的旋轉(zhuǎn)動畫為例,rotate(1turn)轉(zhuǎn)換后是matrix(1, 0, 0, 1, 0, 0),但如果直接寫:
@keyframes spin { to { transform: matrix(1, 0, 0, 1, 0, 0); } }
結(jié)果就是,什么也不會發(fā)生。
結(jié)語只通過一個(gè)transform加上一段神秘代碼,就可以做這樣特別的動畫,我覺得是很有意思的。希望本文的這樣一番解讀,可以幫助你加深對css的transform的理解。
(重新編輯自我的博客,原文地址:http://acgtofe.com/posts/2016...)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/111698.html
摘要:層疊即表示允許以多種方式來描述樣式,一個(gè)元素可以被渲染呈現(xiàn)出多種樣式。可以讓屬性的變化過程持續(xù)一段時(shí)間,而不是立即生效。比如,將元素的顏色從白色改為黑色,通常這個(gè)改變是立即生效的,使用后,將按一個(gè)曲線速率變化。 showImg(https://segmentfault.com/img/bVZwyL?w=900&h=385); CSS 的全稱是 Cascading Style Sheet...
摘要:綜上,上面的代碼的值都應(yīng)該加上,即逐幀動畫在實(shí)現(xiàn)一個(gè)卡通影片或者一個(gè)復(fù)雜的進(jìn)度指示框,或者的標(biāo)志時(shí)這種場景比較適應(yīng)逐幀動畫。這種平滑特性不適用于逐幀動畫的實(shí)現(xiàn)。 緩動效果 回彈動畫效果是比較常見的動畫,比如小球的運(yùn)動、對于尺寸變化和角度變化使用回彈效果可以增強(qiáng)動畫的體驗(yàn)。小面介紹一些簡單的緩動效果的動畫。 彈跳動畫的實(shí)現(xiàn) css中所有過渡和動畫都是跟一條曲線(緩動曲線)有關(guān)的,這條曲線...
摘要:整理一個(gè)繪制環(huán)形進(jìn)度條的,需要的同學(xué)拿去用即可定義繪圖區(qū)域在頁面的任何位置,添加繪圖面板。 showImg(https://segmentfault.com/img/bVrm3V); 整理一個(gè)svg繪制環(huán)形進(jìn)度條的demo,需要的同學(xué)拿去用即可 定義svg繪圖區(qū)域 在html頁面的任何位置,添加svg繪圖面板。定義svg繪圖區(qū)域大小 繪制一個(gè)圓形 cx 和 cy 屬性定義圓點(diǎn)的 x ...
摘要:第一部分是正方體部分,第二部分是中的路徑動畫了,第三部分則是交互旋轉(zhuǎn)。然后在立方體元素上添加鼠標(biāo)點(diǎn)擊事件事件,在回調(diào)函數(shù)中做處理內(nèi)容?;卣{(diào)函數(shù)中先記錄下來鼠標(biāo)點(diǎn)擊的位置。 1.前言 我使用了jquery編寫交互的旋轉(zhuǎn),因?yàn)槌鯇W(xué)所以不太承受,還請見諒。樣式我是寫stylus編碼,自動生成css。 2.正文 先放上一張效果圖showImg(https://segmentfault.com...
閱讀 2313·2023-04-25 16:42
閱讀 1210·2021-11-22 14:45
閱讀 2348·2021-10-19 13:10
閱讀 2833·2021-09-29 09:34
閱讀 3418·2021-09-23 11:21
閱讀 2110·2021-08-12 13:25
閱讀 2201·2021-07-30 15:15
閱讀 3500·2019-08-30 15:54