1. 背景
在制作CSS动画的时候,经常会有这样的需求,
让一个方块 沿着给定的路径 运动。
如果运动路径是不规则的,通过设置top
,left
的属性值,就显得非常困难了。
这时候可以借助svg来实现。
2. svg的path元素
path
元素的形状是通过它的 d属性 定义的,
d 属性的值,是一个“命令+参数”的序列。
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<path d="M 20 30 L 160 180" />
</svg>
<style>
svg {
background: gray;
}
svg path {
stroke: black;
fill: none;
stroke-width: 2;
}
</style>
其中,M 20 30 L 160 180
,包含了2个命令序列,
M 20 30
,表示将画笔移动到坐标20,30
处,
L 160 180
,表示从画笔当前位置,到160,180
位置画直线。
path元素支持多种命令,可以参考这里,curve commands
3. offset-path 与 offset-distance 属性
html元素的CSS样式属性offset-path ,表示偏移路径。
通过指定offset-path
的值为path元素的d
属性值,我们可以实现元素沿着给定的path
路径运动。
<div class="container">
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<path d="M 20 30 L 160 180" />
</svg>
<div class="rect"></div>
</div>
<style>
.container {
position: relative;
}
.container svg {
background: gray;
}
.container svg path {
stroke: black;
fill: none;
stroke-width: 2;
}
.container .rect {
position: absolute;
top: 0;
left: 0;
width: 10px;
height: 10px;
background: darkred;
offset-path: path("M 20 30 L 160 180");
offset-distance: 20%;
}
</style>
其中,offset-distance 指定了元素偏移初始位置的百分比。
4. 动画中设置offset-distance
通过在@keyframes
中逐帧更改offset-distance
,可以实现动画效果。
<div class="container">
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<path d="M 20 30 L 160 180" />
</svg>
<div class="rect"></div>
</div>
<style>
.container {
position: relative;
}
.container svg {
background: gray;
}
.container svg path {
stroke: black;
fill: none;
stroke-width: 2;
}
@keyframes svg-path-animation {
from {
offset-distance: 0%;
}
to {
offset-distance: 100%;
}
}
.container .rect {
position: absolute;
top: 0;
left: 0;
width: 10px;
height: 10px;
background: darkred;
offset-path: path("M 20 30 L 160 180");
offset-distance: 0%;
animation: svg-path-animation 2s ease-in-out 0s infinite normal none;
}
</style>
5. 任意path路径
我们修改path的d
属性为M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80
,
相应的也修改小方块的offset-path
属性。
就可以实现小方块沿着path运动的效果了。
<div class="container">
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<path d="M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80" />
</svg>
<div class="rect"></div>
</div>
<style>
.container {
position: relative;
}
.container svg {
background: gray;
}
.container svg path {
stroke: black;
fill: none;
stroke-width: 2;
}
@keyframes svg-path-animation {
from {
offset-distance: 0%;
}
to {
offset-distance: 100%;
}
}
.container .rect {
position: absolute;
top: 0;
left: 0;
width: 10px;
height: 10px;
background: darkred;
offset-path: path("M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80");
offset-distance: 0%;
animation: svg-path-animation 2s ease-in-out 0s infinite normal none;
}
</style>
参考
MDN: paths
MDN: offset-path
MDN: offset-distance
A How-to Guide to SVG Animation
Scalable Vector Graphics (SVG) 2 - Chapter 9: Paths