CSS之:使用svg路径做关键帧动画
本帖最后由 马黑黑 于 2022-9-13 13:23 编辑 <br /><br /><p>svg路径可以任意设计,通过 path 属性,svg能画出任何图形。CSS对svg的此功能自然不会放过,于是,有一个名叫 offset-path 的CSS属性,一看就知道其意,偏移路径,但不一定知道它用来干啥。嗯,CSS3以前,它不是这个名儿,而是叫 motion-path,这个才一看既知其意,又晓其作用,运动路径。好吧,offset-path的前身是motion-path,是用来做路径运动的。</p><p><br></p>
<p>offset,偏移,大量用于svg,比如针对这个 offset-path,配套的属性还有 offset-distance、offset-rotate 等,这两个在CSS实现svg路径动画中特重要,所以先提出来。顾名思义,offset-distance 是偏移距离之意,offset-rotate 是 偏移过程中如何旋转(auto是默认值,所以没有特殊需要不必设置 offset-rotate 属性)。</p>
<p><br></p>
<p>既是调用svg路径,我们就先来路径,然后在考虑如何在CSS中调用这个路径。这里使用A指令画一个椭圆路径:</p><p><br></p><p><svg width="300" height="200"></p><p><span style="white-space:pre"> </span><path <font color="#ff0000">d=</font><font color="#ff00ff">"M 10 100 A 140 80 0 1 1 290 100 A 140 80 0 0 1 10 100 z"</font> fill="none" stroke="olive"></path></p><p></svg></p><p><br></p><p>上面代码,我们在 300*200 的svg画布上通过 path 路径指令,绘制了一个自身闭合的椭圆(有没有z都是闭合的)。A 是圆弧指令,本帖不解释它的语法。代码中,我们用两个 A 指令画出向上和向下的圆弧,两个圆弧合起来就是椭圆——我们要的是椭圆的路径,它就是 d 的值。效果如下:</p>
<svg width="300" height="200">
<path d="M 10 100 A 140 80 0 1 1 290 100 A 140 80 0 0 1 10 100 z" fill="none" stroke="olive"></path>
</svg>
<p>OK,接下来讨论如何在CSS中调用这个路径做某个对象的运动轨迹。我们先来设计一个CSS盒子,类选择器:</p>
<p><br></p><p>.mybox {</p>
<p><span style="white-space:pre"> </span>--ss: 0s;</p><p><span style="white-space:pre"> </span>position: absolute;</p><p><span style="white-space:pre"> </span>width: 20px;</p><p><span style="white-space:pre"> </span>height: 20px;</p>
<p><span style="white-space:pre"> </span>background: olive;</p><p><span style="white-space:pre"> </span>display: block;</p>
<p><span style="white-space:pre"> </span><font color="#ff0000">offset-path: path("M10 100 A140 80 0 1 1 290 100 A140 80 0 0 1 10 100z");</font></p><p><span style="white-space:pre"> </span><font color="#008000">animation: move 6s var(--ss) linear infinite;</font></p>
<p>}</p>
<p>.box1 { --ss: .25s; background: pink; }</p>
<p>.box2 { --ss: .5s; background: green; }</p>
<p>@keyframes move {</p>
<p><span style="white-space:pre"> </span>to { <span style="white-space:pre"> </span><font color="#0000ff">offset-distance: 100%;</font> }</p>
<p>}</p>
<p><br></p>
<p>这个 .mybox,有一个变量 --ss: 0s; ,用于延时执行动画,首个盒子不延时(0s),.box1 是第二个盒子,延时 0.25s,第三个盒子 .box2延时 0.5s,每个盒子各有自己的背景色。路径的引用在红色代码那里,注意语法、语句。调用动画语句是绿色的代码。关键帧动画是蓝色代码部分,使用了 offset-distance,偏移到 100%。下面是HTML代码:</p>
<p><br></p>
<p><span class="mybox"></span></p><p><span class="mybox box1"></span></p>
<p><span class="mybox box2"></span></p>
<p><br></p>
<p>效果请看:</p>
<p><br></p>
<style>
#papa { margin: auto; width: 600px; height: 300px; position: relative; }
.mybox {
--ss: 0s;
position: absolute;
width: 20px;
height: 20px;
background: olive;
display: block;
offset-path: path("M10 100 A140 80 0 1 1 290 100 A140 80 0 0 1 10 100z");
animation: move 6s var(--ss) linear infinite;
}
.box1 { --ss: .25s; background: pink; }
.box2 { --ss: .5s; background: green; }
@keyframes move {
to { offset-distance: 100%; }
}
</style>
<div id="papa">
<span class="mybox"></span>
<span class="mybox box1"></span>
<span class="mybox box2"></span>
</div> 【附】一楼最后效果的问政代码:
<style>
#papa { margin: auto; width: 600px; height: 300px; position: relative; }
.mybox {
--ss: 0s;
position: absolute;
width: 20px;
height: 20px;
background: olive;
display: block;
offset-path: path("M10 100 A140 80 0 1 1 290 100 A140 80 0 0 1 10 100z");
animation: move 6s var(--ss) linear infinite;
}
.box1 { --ss: .25s; background: pink; }
.box2 { --ss: .5s; background: green; }
@keyframes move {
to { offset-distance: 100%; }
}
</style>
<div id="papa">
<span class="mybox"></span>
<span class="mybox box1"></span>
<span class="mybox box2"></span>
</div>
从代码中可以看到,得到svg路径之后,HTML元素的运动根本就不再需要 svg 参与,我们前面画的椭圆路径图案只是为了演示路径。一切在CSS中完成,只需要一个 offset-path 路径、一个 offset-distance 偏移设置。 本帖最后由 马黑黑 于 2022-9-14 12:25 编辑
CSS Motion Path 规范主要属性:
① offset-path :接收一个 svg 几何路径,作为使用该路径的对象(下称使用对象)的运动轨迹。
语句举例:offset-path: path("M 10,50 H 210");
② offset-distance :控制使用对象基于 offset-path 路径的距离
③ offset-position :指定 offset-path 的初始位置(Chrome暂不支持)
④ offset-anchor :定义使用对象基于路径的锚点(Chrome暂不支持)
⑤ offset-rotate :定义使用对象在路径上的角度朝向,缺省时值为 auto,即能根据路径调整“车身”。
二、为了能够在web页中随意布局运动对象,建议:
① 运动对象使用 position: absolute; ,即绝对定义设定,这是保证运动对象按 offset-path 路径的基础;
② 运动对象设置 offset-distance 属性,关键帧动画配合此值进行终点目标设置。举例说明:假设我们希望使用对象在一个闭合的路径上循环绕行,我们想让它在路径的 25% 处出发,则应定义 offset-distance 为 25%,然后在 @keyframes 关键帧动画里,to 或 100% 的偏移路径设置为 125%;但非闭合路径则根据需要设定,不受此限制。
③ 可以给使用对象添加一个父元素并设定其为与路径大小(即路径所在的svg尺寸)一致、绝对定位,如此可以在web也中更方便移动运动对象到所希望的区域:仅设置父元素的left与top值便可。如果希望路径轨迹一同展现,应将svg代码也作为该父元素的子元素。举个例子:
<div id="mama">
<span class="mybox"></span>
<span class="mybox box1"></span>
<span class="mybox box2"></span>
<svg width="300" height="200" viewBox="0 0 300 200">
<path d="M 10 100 A 140 80 0 1 1 290 100 A 140 80 0 0 1 10 100" fill="none" stroke="olive"></path>
</svg>
</div>
这里,三个 span 元素是使用路径进行运动的对象,即运动元素,随后给出svg代码。酱的话,由于使用对象和路径都包含在 mama 元素中,使用对象就会在路径轨迹上运动。
谢谢老师的精彩分享,感谢问好! A指令看着好麻烦啊,那么多参数,而且不是一下能画出椭圆,还得分两部分画。 这三个小方块原来只要做一个,其他的就用命令就可以弄出来了啊。等着下一楼的解释{:4_173:} 红影 发表于 2022-9-13 16:09
这三个小方块原来只要做一个,其他的就用命令就可以弄出来了啊。等着下一楼的解释
这是将路径用到了CSS关键帧动画,类选择器 mybox 设定了 animation,只要使用了 class="mybox" 的元素,都能按 keyframes 设计的动画运行
梦缘 发表于 2022-9-13 15:42
谢谢老师的精彩分享,感谢问好!
同问 红影 发表于 2022-9-13 16:06
A指令看着好麻烦啊,那么多参数,而且不是一下能画出椭圆,还得分两部分画。
A 指令是 path 路径里最复杂的一个,除开 M 的参数不算,A 需要 7 个参数:
第一个 rx,X轴半径;
第二个 ry,Y轴半径;
第三个 x-axis-rotation,椭圆相对于坐标系的旋转角度;
第四个 large-arc-flag,标记绘制大弧(1)还是小弧(0)部分;
第五个 sweep-flag,标记向顺时针(1)还是逆时针(0)方向绘制圆弧;
第六、七个是 xy,圆弧终点坐标。 马黑黑 发表于 2022-9-13 18:22
A 指令是 path 路径里最复杂的一个,除开 M 的参数不算,A 需要 7 个参数:
第一个 rx,X轴半径;
前几个参数好理解,最后的圆弧终点坐标难理解,比如你这个画半个椭圆,最后的点应该落在长轴的点上,为什么是290呢,哦,哦,我知道了,是X轴半径140要乘以2再加上前面的10,呵呵,本来看迷糊了,边问边还明白了{:4_189:} 马黑黑 发表于 2022-9-13 18:22
A 指令是 path 路径里最复杂的一个,除开 M 的参数不算,A 需要 7 个参数:
第一个 rx,X轴半径;
按你这里的参数的解说,对这个椭圆
("M10 100 A140 80 0 1 1 290 100 A140 80 0 0 1 10 100z");
X轴半径140,Y轴半径80,上下两个弧都是,然后旋转角度全是0,在然后大弧(1)还是小弧(0)这点,上半部是大弧,下半部是小弧(这个不好理解),在然后顺时针(1)还是逆时针(0)方向方面,全是顺时针。最后圆弧终点坐标,上半部落在长轴终点,下半部落在起点。 马黑黑 发表于 2022-9-13 18:17
这是将路径用到了CSS关键帧动画,类选择器 mybox 设定了 animation,只要使用了 class="mybox" 的元素, ...
哦哦,知道了{:4_187:} 红影 发表于 2022-9-13 21:40
哦哦,知道了
关键帧动画的说 红影 发表于 2022-9-13 21:25
前几个参数好理解,最后的圆弧终点坐标难理解,比如你这个画半个椭圆,最后的点应该落在长轴的点上,为什 ...
这个是很难理解的。给画的椭圆,用两个A指令,或许你可以一个一个去查看领会,慢慢来,也不好怎么解释了 红影 发表于 2022-9-13 21:34
按你这里的参数的解说,对这个椭圆
("M10 100 A140 80 0 1 1 290 100 A140 80 0 0 1 10 100z");
X轴半 ...
嗯,怎么说呢,参数4和5的搭配会得出四种形态的圆弧,你要两根各自分开画,慢慢体会 马黑黑 发表于 2022-9-13 22:18
这个是很难理解的。给画的椭圆,用两个A指令,或许你可以一个一个去查看领会,慢慢来,也不好怎么解释了
嗯嗯,可能画几个,能更好地理解。 马黑黑 发表于 2022-9-13 22:14
关键帧动画的说
这个真不错。 马黑黑 发表于 2022-9-13 22:19
嗯,怎么说呢,参数4和5的搭配会得出四种形态的圆弧,你要两根各自分开画,慢慢体会
嗯,估计多动手才能真的弄明白。 红影 发表于 2022-9-13 22:50
这个真不错。
就是借用了svg的 path 路径,一般的CSS说明很少提及甚至只字不提