马黑黑 发表于 2022-9-10 11:06

svg动画之:animateMotion

本帖最后由 马黑黑 于 2022-9-10 11:09 编辑 <br /><br /><p>我们在&nbsp;<a href="https://www.huachaowang.com/forum.php?mod=viewthread&amp;tid=62964&amp;extra=page%3D1">时间</a>&nbsp;一帖里提到过,svg 可以直接驱动文本沿着既定路径移动。试看如下效果,蓝色边框的区域是 svg&nbsp;画布,文字沿着直线路径来回移动。代码和效果如下:</p><p><br></p><p><font color="#8b0000">&lt;svg width="600" height="200" style="border: 1px solid blue; margin: auto; display: block; position: relative;"&gt;</font></p><p><font color="#8b0000">&nbsp; &nbsp; &lt;text x="0" y="5" style="font: bold 2em sans-serif; stroke: red; fill: none;"&gt;月是故乡明</font></p><p><font color="#8b0000">&nbsp; &nbsp; &nbsp; &nbsp; &lt;animateMotion </font><font color="#0000ff">path="M 10 100 H 440 z"</font><font color="#8b0000"> </font><font color="#ff0000">dur</font><font color="#8b0000">="8s" </font><font color="#ff0000">repeatCount</font><font color="#8b0000">="indefinite"&gt;&lt;/animateMotion&gt;</font></p><p><font color="#8b0000">&nbsp; &nbsp; &lt;/text&gt;</font></p><p><font color="#8b0000">&lt;/svg&gt;</font></p>

<svg width="600" height="200" style="border: 1px solid blue; margin: auto; display: block; position: relative;">
    <text x="0" y="5" style="font: bold 2em sans-serif; stroke: red; fill: none;">月是故乡明
      <animateMotion path="M 10 100 H 440 z" dur="8s" repeatCount="indefinite"></animateMotion>
    </text>
</svg>

<p><br>animateMotion&nbsp;可以直接写路径,代码中的蓝色部分就是,上例用&nbsp;path&nbsp;写出了一个从 10&nbsp;开始&nbsp;到 440结束的水平路径,路径中的 z&nbsp;表示闭合路径,这是文本来回移动的依据(运动总是照着路径的,路径闭合意味着头尾相连,直线路径不会头尾相连,就往复循环)。</p><p><br></p><p>animateMotion&nbsp;还有几个重要参数,这里仅就上例做解释:dur&nbsp;必须,运动周期时长;repeatCount,重复次数,可用正整数,也可以用例中的数值(无限数值),不设置此参数时运动一次就停下来。</p><p><br></p><p><font color="#ff0000">animateMotion&nbsp;必须被包裹在调用运动的标签内</font>。上面的例子中,它放在 &lt;text&gt;&nbsp;和 &lt;/text&gt;&nbsp;之内。可能有朋友会问:那么,像圆、矩形、线条之类的svg元素,它们就不能使用&nbsp;animateMotion&nbsp;运动了?因为它们是自闭合标签!答案会令大家满意:能用,自闭合标签在使用&nbsp;animateMotion&nbsp;运动时,写成有起始符、收尾符的标签即可!请看例子,一个矩形代替上面的文本运动:</p><p><br></p><p><font color="#8b0000">&lt;svg width="600" height="200" style="border: 1px solid blue; margin: auto; display: block; position: relative;"&gt;</font></p><p><font color="#8b0000">&nbsp; &nbsp;&nbsp;</font><font color="#ff00ff">&lt;rect</font> <font color="#8b0000">x="0" y="0" width="50" height="30" fill="olive"&gt;</font></p><p><font color="#8b0000">&nbsp; &nbsp; &nbsp; &nbsp; &lt;animateMotion&nbsp;</font><font color="#0000ff">path="M 10 100 H 540 z"</font><font color="#8b0000">&nbsp;</font><font color="#ff0000">dur</font><font color="#8b0000">="8s"&nbsp;</font><font color="#ff0000">repeatCount</font><font color="#8b0000">="indefinite"&gt;&lt;/animateMotion&gt;</font></p><p><font color="#8b0000">&nbsp; &nbsp;&nbsp;</font><font color="#ff00ff">&lt;/rect&gt;</font></p><p><font color="#8b0000">&lt;/svg&gt;</font></p><p><font color="#8b0000"><br></font></p><p>通常,rect&nbsp;标签都是写成 <font color="#8b0000">&lt;rect x="10" y="10" ....&nbsp;</font> <font color="#ff0000">/&gt;</font>&nbsp;这样的自闭合方式,为了调用&nbsp;animateMotion&nbsp;就必须包裹它,所以也能有终止标签符号 &lt;/rect&gt;!</p><p><br></p>

马黑黑 发表于 2022-9-10 11:07

本帖最后由 马黑黑 于 2022-9-10 13:10 编辑 <br /><br /><p>将 animateMotion 所使用的路径写在自己代码内不是官方建议的方法,但在路径极简且无需反复调用路径时,可以考虑。官方建议 animateMotion 使用路径的方法是先设计路径,再使用 mpath 标签指定所使用的路径。以l类似一楼的直线路径为例,我们来看看如何实现:</p><p><br></p><p>&lt;svg width="600" height="200" viewBox="0 0 600 200" style="border: 1px solid"&gt;</p><p><span style="white-space:pre">        </span>&lt;path id="<font color="#ff0000">path1</font>" d="M 50 100 H 530 z" stroke="red" /&gt;</p><p><span style="white-space:pre">        </span>&lt;rect x="10" <font color="#008000">y="-20"</font> width="50" height="40" fill="olive"&gt;</p><p><span style="white-space:pre">                </span>&lt;animateMotion dur="8s" r<font color="#0000ff">epeatCount="5"</font>&gt;</p><p><span style="white-space:pre">                        </span>&lt;mpath xlink:href="<font color="#ff0000">#path1</font>" /&gt;</p><p><span style="white-space:pre">                </span>&lt;/animateMotion&gt;</p><p><span style="white-space:pre">        </span>&lt;/rect&gt;</p><p>&lt;/svg&gt;</p><p><br></p><p><br></p>

<svg width="600" height="200" viewBox="0 0 600 200" style="border: 1px solid">
        <path id="path1" d="M 50 100 H 530 z" stroke="red"></path>
        <rect x="10" y="-20" width="50" height="40" fill="olive">
                <animateMotion dur="8s" repeatCount="5">
                        <mpath xlink:href="#path1"></mpath>
                </animateMotion>
        </rect>
</svg>

<p><br>mpath&nbsp;以&nbsp;animateMotion&nbsp;的子标签出现,只负责为 animateMotion&nbsp;指定前面设计的&nbsp;path&nbsp;路径。</p><p><br></p><p>在上面的例子里,矩形的 y 值为什么设定为 -20&nbsp;即矩形的高度的一半?根据&nbsp;rect&nbsp;的(xy)坐标,当它处于静止状态时,它的位置又在哪里?又,当矩形根据 animateMotion&nbsp;的设定投入运动中,它为什么在路径x线Y轴的正中央?为了展示这一点,这里将&nbsp;animateMotion&nbsp;的&nbsp;repeatCount&nbsp;设置为 5,运行 5&nbsp;次后动画会停下来,然后可以理解:矩形的&nbsp;xy坐标&nbsp;的设置,当基于路径运动时应参照路径的某些情形(如初始path坐标或xy坐标中全部或某一个轴)进行设定,当矩形是静止展现时,则应以&nbsp;svg&nbsp;的左上角(0,0)做基点设定矩形的位置。</p><p><br></p><p>迄今为止,我们还没有令运动对象以曲线作为运动路径。这里,设计一条三次贝塞尔曲线,先看效果:</p><p><br></p>
<svg width="600" height="200" viewBox="0 0 600 200" style="border: 1px solid">
        <path id="path2" d="M 0 0 C 260 300, 400 20, 600 200" fill="none" stroke="red"></path>
        <rect x="0" y="-20" width="50" height="40" fill="olive">
                <animateMotion dur="3s" rotate="auto" repeatCount="indefinite">
                        <mpath xlink:href="#path2"></mpath>
                </animateMotion>
        </rect>
</svg>
<p><br>代码:</p><p><br></p><p>&lt;svg width="600" height="200" viewBox="0 0 600 200" style="border: 1px solid"&gt;</p><p><span style="white-space:pre">        </span>&lt;path id="<font color="#ff0000">path2</font>" <font color="#0000ff">d="M 0 0 C 260 300, 400 20, 600 200"</font> fill="none" stroke="red" /&gt;</p><p><span style="white-space:pre">        </span>&lt;rect x="0" y="-20" width="50" height="40" fill="olive"&gt;</p><p><span style="white-space:pre">                </span>&lt;animateMotion dur="3s" <font color="#ff00ff">rotate="auto"</font> repeatCount="indefinite"&gt;</p><p><span style="white-space:pre">                        </span>&lt;mpath xlink:href="<font color="#ff0000">#path2</font>" /&gt;</p><p><span style="white-space:pre">                </span>&lt;/animateMotion&gt;</p><p><span style="white-space:pre">        </span>&lt;/rect&gt;</p><p>&lt;/svg&gt;</p><p><br></p><p>蓝色代码,<span style="color: rgb(0, 0, 255);">d="M 0 0 C 260 300, 400 20, 600 200"</span>,M 0 0 ,画笔起笔处也是曲线开始点的坐标,C&nbsp;是三次贝塞尔曲线指令(CurveTo的缩写),所带的三组参数,最后一组是曲线的终点坐标,第一、第二组是两个控制点坐标。这个路径没有用小写字母 z&nbsp;闭合,因为这条曲线闭合了构不成合理的运行轨道。</p><p><br></p><p>animateMotion&nbsp;代码中还有一个重要的设置,<span style="color: rgb(255, 0, 255);">rotate="auto"</span>,这是叫矩形能够根据路径自动调整“车身”的意思,没有这句,矩形行进的效果没那么好。</p>

红影 发表于 2022-9-10 11:24

这个怎么好像要等上一会才会开始运动?

马黑黑 发表于 2022-9-10 11:43

红影 发表于 2022-9-10 11:24
这个怎么好像要等上一会才会开始运动?

立即动的。不知你的浏览器是什么

小辣椒 发表于 2022-9-10 12:59

今天这个播放器教程的歌词就这样做的吧,黑黑精彩不断{:4_178:}

马黑黑 发表于 2022-9-10 13:12

小辣椒 发表于 2022-9-10 12:59
今天这个播放器教程的歌词就这样做的吧,黑黑精彩不断

那个播放器没有用上这里的 动画,它是基于纯粹的CSS动画的,那个帖子里说的清楚

梦缘 发表于 2022-9-10 15:23

欣赏老师的精彩动画代码,多谢分享。祝您双节幸福快乐!{:4_204:}

马黑黑 发表于 2022-9-10 16:45

梦缘 发表于 2022-9-10 15:23
欣赏老师的精彩动画代码,多谢分享。祝您双节幸福快乐!

喝水{:4_191:}

红影 发表于 2022-9-10 18:27

马黑黑 发表于 2022-9-10 11:07
本帖最后由 马黑黑 于 2022-9-10 13:10 编辑 将 animateMotion 所使用的路径写在自己代码内不是官方建议的 ...
这个曲线运动的好美,像是滑滑梯{:4_187:}

马黑黑 发表于 2022-9-10 19:04

红影 发表于 2022-9-10 18:27
这个曲线运动的好美,像是滑滑梯

曲线运动实际上是现实中最常见的运动。曲线同时也是很美的。

红影 发表于 2022-9-10 20:57

马黑黑 发表于 2022-9-10 19:04
曲线运动实际上是现实中最常见的运动。曲线同时也是很美的。

这个以后倒是可以派派用途呢,真的很好看。

上海朝阳 发表于 2022-9-10 21:16

中秋大家快乐!

马黑黑 发表于 2022-9-10 21:17

上海朝阳 发表于 2022-9-10 21:16
中秋大家快乐!

同乐同乐

马黑黑 发表于 2022-9-10 21:19

红影 发表于 2022-9-10 20:57
这个以后倒是可以派派用途呢,真的很好看。

嗯,你设计一个二次、三次贝塞尔曲线不是个问题。记得你设计的蜜蜂运动节点,看得出你在路径设计方面是好手。

红影 发表于 2022-9-10 23:20

马黑黑 发表于 2022-9-10 21:19
嗯,你设计一个二次、三次贝塞尔曲线不是个问题。记得你设计的蜜蜂运动节点,看得出你在路径设计方面是好 ...

那个没什么啊,只不过是取点位值而已,而且不用太精确,差不多就行了{:4_173:}

马黑黑 发表于 2022-9-11 07:38

红影 发表于 2022-9-10 23:20
那个没什么啊,只不过是取点位值而已,而且不用太精确,差不多就行了

路径就是设置各个点的位置,当然,需要精准

红影 发表于 2022-9-11 10:21

马黑黑 发表于 2022-9-11 07:38
路径就是设置各个点的位置,当然,需要精准

嗯,很多地方取点必须准确,看上去才不怪异。但蜜蜂那个不用太准确{:4_173:}

马黑黑 发表于 2022-9-11 10:21

红影 发表于 2022-9-11 10:21
嗯,很多地方取点必须准确,看上去才不怪异。但蜜蜂那个不用太准确

嗯,这个知道

红影 发表于 2022-9-11 10:53

马黑黑 发表于 2022-9-11 10:21
嗯,这个知道

当图图中有其他参照,则,则取点必须准确。因为参照之下的差异会很明显。

马黑黑 发表于 2022-9-11 11:21

红影 发表于 2022-9-11 10:53
当图图中有其他参照,则,则取点必须准确。因为参照之下的差异会很明显。

如果可以,尽可能精准取点。
页: [1] 2
查看完整版本: svg动画之:animateMotion