用一個簡單的例子來討論,讓一幅頭像圖片沿著環形路徑動起來。它的結構代碼如下:
<div class="path">

</div>
在考慮動畫之前,先給它加上基本的樣式:
背景圓形的直徑為300px
這時候,我們就開始考慮讓頭像沿著外圈的橙色大圓以轉圈的方式移動了:
@keyframes spin {
to {transform:rotate(1turn);}
}
.avatar {
animation: spin 3s infinite linear;
transform-origin: 50% 150px; /*路徑的半徑:150px*/
不過,此時,效果卻是不夠完美的,因為頭像沿著環形路徑轉動的同時,頭像自身也贊自轉:
但是我們想要的效果是:頭像沿著環形進行移動,同時保持自己本來的朝向。
有什么辦法呢:用內層的變形來抵消外層的變形效果
此時需要兩層元素,給頭像套上一層額外的div:
<div class="path">
<div class="avatar">

</div>
</div>
我們給頭像元素設置另外一個旋轉動畫,讓它以相反的方向自轉一周,把頭像的動畫設置為相反的角度范圍(360 - 0deg)即可:
@keyframes spin {
to {transform:rotate(1turn);}
}
@keyframes spin-reverse{
from {transform:rotate(1turn);}
}
.avatar {
animation: spin 3s infinite linear;
transform-origin: 50% 150px;
}
.avatar > img {
animation: spin-reverse 3s infinite linear;
}
終于得到我們想要的效果了
但是,這段代碼是不是還可以繼續改進呢?比如說兩套動畫中的各個參數其實是重復了兩次了。如果我們需要調整動畫周期的話,還要修改兩處。我們讓內層動畫從父元素那里繼承所有的動畫屬性,然后把動畫名字覆蓋掉就可以了:
@keyframes spin {
to {transform:rotate(1turn);}
}
@keyframes spin-reverse{
from {transform:rotate(1turn);}
}
.avatar {
animation: spin 3s infinite linear;
transform-origin: 50% 150px;
}
.avatar > img {
animation: inherit;
animation-name: spin-reverse;
}
不過,不過!我們可不可以利用一套關鍵幀實現兩套旋轉動畫化?利用reverse 這個值:
@keyframes spin {
to {transform:rotate(1turn);}
}
.avatar {
animation: spin 3s infinite linear;
transform-origin: 50% 150px;
}
.avatar > img {
animation: inherit;
animation-direction: reverse; /*原始動畫的反向版本*/
}
這樣就差不多了,但是也算不上完美,畢竟需要一層額外的元素。
單個元素的解決方案:
我們把頭像放在圓心并以此作為起點:
最終的代碼是這樣的:
@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 3s infinite linear;
}
transform-origin 可以用 translate() 來代替。
最后仍然能得到我們想要的效果,并且代碼更加簡潔了。
<u>查看demo</u>
demo里面代碼和文章中有點不一樣,原因是頭像圖片使用的是網絡上的圖片,并且用css進行了縮小和剪裁。
參考書籍:Lea Verou《CSS揭秘》