在 CSS 動畫中,咱們日常都會經過 CSS Animation 和 CSS Transform 等實現一些簡單的 CSS 動畫。然而,要想讓動畫對象沿着一條路徑進行移動,仍是有一些難點的。CSS Motion Path 標準的出現,讓開發者可以給動畫對象定義一條動畫路徑,配合 keyframe 等操做,輕鬆實現讓一個物體沿着一條路徑進行動畫。css
Motion Path Level 1 從 2015 年 4 月 9 日發表第一個工做草案以來,通過3年多的時間,發展得已經比較成熟了,同時 Google Chrome、Opera 瀏覽器也是第一批可以支持大部分草案標準功能的瀏覽器。chrome
下面咱們就來了解一下吧。瀏覽器
既然是要讓對象沿着一條路徑走,那麼本標準中最重要的點就在如何定義路徑上了。bash
offset-path
即爲定義路徑的屬性,它可以接受 ray()
、CSS Shaps 中的圖形 以及可以接受相似 SVG 路徑定義的 path()
。ide
在 Chrome 中,目前叫 motion-pathpost
ray()
即爲輻射線。它以容器的中心爲圓心,在容器中嵌入一個可以嵌入的最大圓形,結合自定義的夾角,將圓心與邊上的點相連,造成路徑。動畫
ray
接受三個參數,分別是角度,大小以及設置是否讓對象徹底包含在路徑內。url
用下面的例子進行一一解釋spa
<style>
body {
transform-style: preserve-3d;
width: 200px;
height: 200px;
}
.box {
width: 50px;
height: 50px;
offset-position: 50% 50%;
offset-distance: 100%;
offset-rotate: 0deg;
}
#redBox {
background-color: red;
offset-path: ray(45deg closest-side);
}
#blueBox {
background-color: blue;
offset-path: ray(180deg closest-side);
}
</style>
<body>
<div class="box" id="redBox"></div>
<div class="box" id="blueBox"></div>
</body>
複製代碼
即 CSS 中的角度定義,如上圖,45deg 和 90deg 分別造成 45 度和 90 度的夾角。.net
第二個大小參數決定了路徑的長短,它支持如下的屬性
屬性值 | 含義 |
---|---|
closest-side | 初始位置到最近一邊的距離 |
closest-corner | 初始位置到最近一角的距離 |
farthest-side | 初始位置到最遠一遍的距離 |
farthest-corner | 初始位置到最遠一角的距離 |
sides | 初始位置到交線的距離 |
設置對象是否徹底包含在路徑之中
若是上述例子設置了 conatin,兩個 box 將會徹底包含在路徑以內
offset-path: ray(90deg, closest-side, contain)
咱們還能利用 CSS 中的形狀來定義動做路徑,CSS 中的形狀咱們已經不陌生了,例如inset()
, circle()
, ellipse()
, polygon()
,甚至還能使用盒模型的數值如 margin-box
, border-box
, padding-box
, content-box
。
下面這個例子使用了 margin-box
的邊做爲動做路徑:
<style>
body {
width: 500px;
height: 300px;
border-radius: 80px;
border: dashed aqua;
margin: 0;
}
#blueBox {
width: 40px;
height: 20px;
background-color: blue;
offset-path: margin-box;
}
</style>
<body>
<div id="blueBox"></div>
</body>
複製代碼
path()
能夠接受 SVG 中的幾何描述數據做爲動做路徑
.path {
offset-path: path('M150 0 L75 200 L225 200 Z');
}
複製代碼
如上代碼使用 SVG 描述一個三角形,那麼這個對象的動做路徑即爲這個三角形,那麼他的初始位置以及初始方向,能夠參考 SVG 相關標準進行設定。
url 與 上面的 path()
相同,path()
直接將 SVG 幾何描述內容寫到 CSS 中,url 則能夠直接引用 SVG 文件。
offset-distance
用於設定對象在路徑上的位置。
<style>
body {
transform-style: preserve-3d;
width: 300px;
height: 300px;
border: dashed gray;
border-radius: 50%;
}
.circleBox {
position: absolute;
left: 50%;
top: 50%;
width: 40px;
height: 40px;
background-color: red;
border-radius: 50%;
}
#circle1 {
offset-path: ray(0deg farthest-side);
offset-distance: 50%;
}
#circle2 {
offset-path: ray(90deg farthest-side);
offset-distance: 20%;
}
#circle3 {
offset-path: ray(225deg farthest-side);
offset-distance: 100%;
}
</style>
<body>
<div class="circleBox" id="circle1"></div>
<div class="circleBox" id="circle2"></div>
<div class="circleBox" id="circle3"></div>
</body>
複製代碼
上面例子中,經過設定三個不一樣的offset-distance
設定對應對象在路徑上的位置分別爲 50%, 20%, 100%。
那麼對於 SVG 的幾何圖形,咱們所設定的一些路徑可能沒有閉合,那麼 offset-distance
設定超過 100% 會怎麼樣呢?
<style>
.item {
width: 100px;
height: 40px;
offset-position: 0% 0%;
offset-path: path('m 0 0 h 200 v 150');
}
#box1 {
background-color: red;
offset-distance: -280%;
}
#box2 {
background-color: green;
offset-distance: 190%;
}
</style>
<body>
<div class="item" id="box1"></div>
<div class="item" id="box2"></div>
</body>
複製代碼
能夠看到,兩個分別設置在 -280% 和 +190% 的位置,最終因爲路徑沒有造成閉合,兩個對象停留在最小和最大的可達位置。
<style>
.item {
width: 100px;
height: 40px;
offset-position: 0% 0%;
offset-path: path('m 0 0 h 200 v 150 z');
}
#box1 {
background-color: red;
offset-distance: -280%;
}
#box2 {
background-color: green;
offset-distance: 190%;
}
</style>
<body>
<div class="item" id="box1"></div>
<div class="item" id="box2"></div>
</body>
複製代碼
上面的例子則演示了閉合路徑的狀態,兩個對象都可在路徑上「循環」移動。
offset-position
指定了路徑自己的初始位置在哪裏,能夠提供屬性值auto
或者指定的位置。若是offset-position
爲auto
而且position
不爲static
,那麼默認的offset-position
則爲position
的位置。
<style>
#wrap {
position: relative;
width: 300px;
height: 300px;
border: 1px solid black;
}
#box {
width: 100px;
height: 100px;
background-color: green;
position: absolute;
top: 100px;
left: 80px;
offset-position: auto;
offset-anchor: center;
offset-path: ray(45deg);
}
</style>
<body>
<div id="wrap">
<div id="box"></div>
</div>
</body>
複製代碼
須要移動的對象可能不必定得是對象的正中心,咱們想要自定義對象的錨點,則能夠經過offset-anchor
來實現。
#plane {
offset-anchor: center;
}
複製代碼
上面例子指定了對象的錨點在中心位置。
<style>
body {
transform-style: preserve-3d;
width: 300px;
height: 300px;
border: 2px solid gray;
border-radius: 50%;
}
.box {
width: 50px;
height: 50px;
background-color: orange;
offset-position: 50% 50%;
offset-distance: 100%;
offset-rotate: 0deg;
}
#item1 {
offset-path: ray(45deg closest-side);
offset-anchor: right top;
}
#item2 {
offset-path: ray(135deg closest-side);
offset-anchor: right bottom;
}
#item3 {
offset-path: ray(225deg closest-side);
offset-anchor: left bottom;
}
#item4 {
offset-path: ray(315deg closest-side);
offset-anchor: left top;
}
</style>
<body>
<div class="box" id="item1"></div>
<div class="box" id="item2"></div>
<div class="box" id="item3"></div>
<div class="box" id="item4"></div>
</body>
複製代碼
上面例子中指定了四個矩形的四個不一樣的錨點位置。
若是 offset-anchor
的屬性值爲 auto
,有以下規則進行計算:
條件 | 結果 |
---|---|
offset-path: none; offset-position: 非 auto; |
取 offset-position 的值 |
offset-anchor: auto; offset-path: none; |
與 background-position 行爲相同 |
若是上述都不符合 | 取 transform-origin 的值 |
<style>
body {
width: 500px;
height: 500px;
}
.box {
background-color: mediumpurple;
offset-path: none;
offset-anchor: auto;
}
#item1 {
offset-position: 90% 20%;
width: 60%;
height: 20%;
}
#item2 {
offset-position: 100% 100%;
width: 30%;
height: 10%;
}
#item3 {
offset-position: 50% 100%;
width: 20%;
height: 60%;
}
#item4 {
offset-position: 0% 100%;
width: 30%;
height: 90%;
}
</style>
<body>
<div class="box" id="item1"></div>
<div class="box" id="item2"></div>
<div class="box" id="item3"></div>
<div class="box" id="item4"></div>
</body>
複製代碼
上面例子展現了,offset-anchor
爲 auto
時,錨點的位置計算結果。
offset-rotate
指定了對象的旋轉角度或是如何自動旋轉。
屬性值 | 效果 |
---|---|
auto | 對象根據當前路徑的朝向進行旋轉 若是對 offset-distance 進行動畫,對象也會隨着當前點的朝向進行旋轉 |
reverse | 與 auto 效果相同,但與朝向相反 |
自定義角度 | 對象始終朝着一個方向旋轉 |
當屬性值爲 auto
時,隨着 offset-distance
的改變,角度也會自動改變
當屬性值爲 reverse
時,角度與朝向相反
當屬性值爲 -45deg
時,角度始終不變