马黑黑 发表于 2023-12-13 09:30

svg之 animateMotion 路径动画(二)

本帖最后由 马黑黑 于 2023-12-13 09:37 编辑 <br /><br /><h3>svg之 animateMotion 路径动画(二)</h3>
<p><br></p>
<p>本节,先讲讲 &lt;animateMotion&gt; 元素的<mark> mpath </mark>子元素,它使 &lt;animateMotion&gt; 元素能够引用一个外部的<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">
&lt;svg&gt;
        &lt;path id="mypath"&gt;
        &lt;rect&gt;
                &lt;animateMotion&gt;
                        &lt;mpath xlink:href="#mypath"&gt;&lt;/mpath&gt;
                &lt;/animateMotion&gt;
        &lt;/rect&gt;
&lt;/svg&gt;

</div>

<p>mpath的作用和animateMotion中的path属性一样,都是为animateMotion指定运动路径。由于路径可能很长,所以svg的开发者创建了mpath子元素,用于避免元素的属性表达过长的现象。<br><br></p>
<p>接下来我们讲讲动画标签与驱动对象标签的代码分离。animateMotion 和 animate、animateTransform 一样,标签可以游离于运动对象即元素之外,通过元素的 id 来识别并对之驱动。代码结构举例如下:<br><br></p>

<div class="svgCode">
&lt;svg&gt;
        &lt;path id="mypath"&gt;
        &lt;rect id="rectbox"&gt;&lt;/rect&gt;
        &lt;animateMotion xlink:href="#rectbox"&gt;
                &lt;mpath xlink:href="#mypath"&gt;&lt;/mpath&gt;
        &lt;/animateMotion&gt;
&lt;/svg&gt;

</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('<','&lt;');
                item = item.replaceAll('>','&gt;');
                item = item.replaceAll('\t','&nbsp;&nbsp;&nbsp;&nbsp;');
                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>

幸运草 发表于 2023-12-13 09:42

沙发{:6_244:}

幸运草 发表于 2023-12-13 09:43

鼠标上去那个小方块就开始跑啦{:6_228:}

红影 发表于 2023-12-13 09:48

有填充色好,就可以更直观地看出元素到底在路径的哪一侧运动了。

红影 发表于 2023-12-13 10:03

赶紧又回去复习了一下animateMotion 路径动画(一),那个是把animateMotion 动画路径嵌在矩形里的,这个是可以单独定义路径,然后在矩形动画里用 mpath 子元素来调用。

红影 发表于 2023-12-13 10:05

甚至矩形和路径都可以单独单独设置,然后在动画里通过id分别调用。

红影 发表于 2023-12-13 10:06

有了这个,不用一堆东西挤在一起,感觉的确会好很多{:4_187:}

马黑黑 发表于 2023-12-13 12:52

幸运草 发表于 2023-12-13 09:43
鼠标上去那个小方块就开始跑啦

{:4_181:}

马黑黑 发表于 2023-12-13 12:53

红影 发表于 2023-12-13 09:48
有填充色好,就可以更直观地看出元素到底在路径的哪一侧运动了。

描边也可以,stroke

马黑黑 发表于 2023-12-13 12:53

红影 发表于 2023-12-13 10:06
有了这个,不用一堆东西挤在一起,感觉的确会好很多

代码无需过多的嵌套

马黑黑 发表于 2023-12-13 12:53

红影 发表于 2023-12-13 10:03
赶紧又回去复习了一下animateMotion 路径动画(一),那个是把animateMotion 动画路径嵌在矩形里的,这个是 ...

{:4_181:}

马黑黑 发表于 2023-12-13 12:54

红影 发表于 2023-12-13 10:05
甚至矩形和路径都可以单独单独设置,然后在动画里通过id分别调用。

这是极好的做法

红影 发表于 2023-12-13 16:38

马黑黑 发表于 2023-12-13 12:53
描边也可以,stroke

嗯嗯,看得出是沿着线路的一边行进的呢。

红影 发表于 2023-12-13 16:39

马黑黑 发表于 2023-12-13 12:53
代码无需过多的嵌套

是啊,这样更容易看得明白呢{:4_187:}

红影 发表于 2023-12-13 16:39

马黑黑 发表于 2023-12-13 12:53


隔了几天,已经把前面那个忘得差不多了,正好借机去复习一下{:4_173:}

红影 发表于 2023-12-13 16:41

马黑黑 发表于 2023-12-13 12:54
这是极好的做法
“本节,先讲讲 <animateMotion> 元素的 mpath 子元素。。。”
看起来它还有其他的子元素?

小辣椒 发表于 2023-12-22 22:01

这个我飘过,太多文字了{:4_198:}

马黑黑 发表于 2023-12-22 22:36

小辣椒 发表于 2023-12-22 22:01
这个我飘过,太多文字了

{:4_172:}
页: [1]
查看完整版本: svg之 animateMotion 路径动画(二)