svg之 animateMotion 路径动画(二)
本帖最后由 马黑黑 于 2023-12-13 09:37 编辑 <br /><br /><h3>svg之 animateMotion 路径动画(二)</h3><p><br></p>
<p>本节,先讲讲 <animateMotion> 元素的<mark> mpath </mark>子元素,它使 <animateMotion> 元素能够引用一个外部的<path>元素作为运动路径的定义。如此,animateMotion的path属性可以休息,将路径定义的工作交由animateMotion的子元素 mpath 负责。以下效果与上节(一)的示例完全一样,只是,你从后面提供的代码中可以发现,我们用了 mpath 子元素来描述运动路径,而外部路径我们用淡蓝色做了填充:<br><br></p>
<svg id="mysvg" width="400" height="200" viewBox="0 0 200 100" style="border: 1px solid gray;">
<path
id="mypath"
d="M20,50 C20,-50 180,150 180,50 C180-50 20,150 20,50 z"
fill="lightblue"
stroke="none"
stroke-width=".5"
/>
<rect width="10" height="10" fill="navy">
<animateMotion
dur="8s"
repeatCount="1"
rotate="auto"
begin="0s;mouseover"
restart="whenNotActive"
fill="freeze"
>
<mpath xlink:href="#mypath" />
</animateMotion>
</rect>
</svg>
<p>上面的代码我尝试采用 ol+li 即有序列表实现带行号的代码展现机制,长代码行不好再人工折行(但它会根据浏览器的宽度尺寸自动折行),给阅读带来一定困扰。为方便理解 mpath 子元素,我将上述代码抽离出主干结构,可对照上述代码加以理解:<br><br></p>
<div class="svgCode">
<svg>
<path id="mypath">
<rect>
<animateMotion>
<mpath xlink:href="#mypath"></mpath>
</animateMotion>
</rect>
</svg>
</div>
<p>mpath的作用和animateMotion中的path属性一样,都是为animateMotion指定运动路径。由于路径可能很长,所以svg的开发者创建了mpath子元素,用于避免元素的属性表达过长的现象。<br><br></p>
<p>接下来我们讲讲动画标签与驱动对象标签的代码分离。animateMotion 和 animate、animateTransform 一样,标签可以游离于运动对象即元素之外,通过元素的 id 来识别并对之驱动。代码结构举例如下:<br><br></p>
<div class="svgCode">
<svg>
<path id="mypath">
<rect id="rectbox"></rect>
<animateMotion xlink:href="#rectbox">
<mpath xlink:href="#mypath"></mpath>
</animateMotion>
</svg>
</div>
<p>上述结构性的代码,我们首先给矩形 rect 赋予一个 id,然后在 animateMotion 代码内部加一个 xlink:href 属性,其属性值指向矩形 id。这里,id 与 animateMotion 子元素 mpath 没有直接关系,它具体负责的仅是路径,它的 xlink:href 属性指向路径 id。<br><br></p>
<p>最后,我们用上述结构改造一下本节开头给出的示例代码,请看效果和代码:<br><br></p>
<svg id="mysvg1" width="400" height="200" viewBox="0 0 200 100" style="border: 1px solid gray;">
<path id="mypath" d="M20,50 C20,-50 180,150 180,50 C180-50 20,150 20,50 z" fill="lightgreen" stroke="none" stroke-width=".5"/>
<rect id="rectbox" width="10" height="10" fill="green" />
<animateMotion xlink:href="#rectbox" dur="8s" repeatCount="1" rotate="auto" begin="0s;mouseover" restart="whenNotActive" fill="freeze">
<mpath xlink:href="#mypath" />
</animateMotion>
</svg>
<script>
(function() {
let createCode = (ele,inner) => {
let cssCode = `margin: 10px 0; padding: 8px;font: normal 16px Consolas, courier, monospace;background: #f1f1f1;`;
let strAr = (inner ? ele.innerHTML.trim() : ele.outerHTML).split('\n');
strAr.forEach((item,key) => {
item = item.replaceAll('<','<');
item = item.replaceAll('>','>');
item = item.replaceAll('\t',' ');
strAr = '<li>' + item + '</li>';
});
let outstr = '<ol>' + strAr.join('\n') + '</ol>';
if(inner == false) {
let papaNode = ele.parentNode;
let sonNode = document.createElement('div');
sonNode.style.cssText = cssCode;
sonNode.innerHTML = outstr;
papaNode.insertBefore(sonNode,ele.nextSibling);
}else{
ele.style.cssText += cssCode;
ele.innerHTML = outstr;
}
};
let svgCode = document.querySelectorAll('.svgCode');
createCode(mysvg,false);
createCode(svgCode,true);
createCode(svgCode,true);
createCode(mysvg1,false);
})();
</script> 沙发{:6_244:} 鼠标上去那个小方块就开始跑啦{:6_228:} 有填充色好,就可以更直观地看出元素到底在路径的哪一侧运动了。 赶紧又回去复习了一下animateMotion 路径动画(一),那个是把animateMotion 动画路径嵌在矩形里的,这个是可以单独定义路径,然后在矩形动画里用 mpath 子元素来调用。
甚至矩形和路径都可以单独单独设置,然后在动画里通过id分别调用。 有了这个,不用一堆东西挤在一起,感觉的确会好很多{:4_187:} 幸运草 发表于 2023-12-13 09:43
鼠标上去那个小方块就开始跑啦
{:4_181:} 红影 发表于 2023-12-13 09:48
有填充色好,就可以更直观地看出元素到底在路径的哪一侧运动了。
描边也可以,stroke 红影 发表于 2023-12-13 10:06
有了这个,不用一堆东西挤在一起,感觉的确会好很多
代码无需过多的嵌套 红影 发表于 2023-12-13 10:03
赶紧又回去复习了一下animateMotion 路径动画(一),那个是把animateMotion 动画路径嵌在矩形里的,这个是 ...
{:4_181:} 红影 发表于 2023-12-13 10:05
甚至矩形和路径都可以单独单独设置,然后在动画里通过id分别调用。
这是极好的做法 马黑黑 发表于 2023-12-13 12:53
描边也可以,stroke
嗯嗯,看得出是沿着线路的一边行进的呢。 马黑黑 发表于 2023-12-13 12:53
代码无需过多的嵌套
是啊,这样更容易看得明白呢{:4_187:} 马黑黑 发表于 2023-12-13 12:53
隔了几天,已经把前面那个忘得差不多了,正好借机去复习一下{:4_173:} 马黑黑 发表于 2023-12-13 12:54
这是极好的做法
“本节,先讲讲 <animateMotion> 元素的 mpath 子元素。。。”
看起来它还有其他的子元素? 这个我飘过,太多文字了{:4_198:} 小辣椒 发表于 2023-12-22 22:01
这个我飘过,太多文字了
{:4_172:}
页:
[1]