马黑黑 发表于 2023-11-19 08:04

svg动画之 animate(一)

<style>
.papa > p { margin: 10px 0; }
.hCode { display: block; padding: 10px 10px 10px 50px; font: normal 15px/20px Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; background: #F7EFE6; overflow-x: auto; tab-size: 4; position: relative; }
.hCode::before { position: absolute; content: attr(data-line); left: 0; top: 0; padding: 10px; font: inherit; color: #999; text-align: right; border-right: 1px solid tan; }
.rred { color: red; }
.zs { color: green; }
</style>

<div class="papa">
        <h2>svg动画之 animate(一)</h2>
        <p>介绍svg动画之前先简单了解一下 SMIL:SMIL 全称为 Synchronized Multimedia Integration Language,意为同步多媒体集成语言,于上世纪末由 W3C 正式推出。发行以来被广泛应用于基于XML的语言。svg因为基于XML,自然可以使用SMIL动画,通常大家都称为svg动画,但是,我们要明白的是,svg动画叫 SVG animation with SMIL,基于 SMIL 的svg动画。svg动画主要有如下几种:</p>
<pre class="hCode">
<span class="zs">set</span>set也被视为svg动画的一种,但其实它只是 animate 的一个简化版本
<span class="rred">animate</span>属性动画
<span class="rred">animateTransform</span>转换属性(如transform)动画
<span class="rred">animateMotion</span> 路径动画
<span class="zs">animatecolor</span> 颜色属性值相关动画,已被废弃,可用 animate 实现
</pre>
        <p>总共也就 3.5 种。本节专门介绍 svg 的 <span class="rred">animate</span> 动画,附带讲讲 <span class="rred">set</span> 动画。</p>
        <p>假如我们在svg画布上绘制了一个圆:</p>

<pre class="hCode" data-line="1">
&lt;svg style="width: 400px; height: 120px; border: 1px solid gray;"&gt;
        &lt;circle cx="40" cy="60" r="30" fill="green" /&gt;
&lt;/svg&gt;
</pre>

        <svg style="width: 400px; height: 120px; border: 1px solid gray;">
                <circle cx="40" cy="60" r="30" fill="green" />
        </svg>

        <p>现在,我们想让这个圆自左向右移动。animate 动画就是专门用来实现此类功能的,它允许我们在指定的周期时间内改变元素的指定属性来达成动画效果。圆要自左向右移动,就需要改变圆心坐标 {cx,cy} 中的cx,因为它决定了圆的水平位置。animate 是一个标签,它要包含在运动元素标签之内才能作用于运动元素,故此,circle标签要写成非自闭合标签的样子。以下代码,在上述代码基础上加入了 animate 标签,animate 标签的属性我们随后会一一解释:</p>
       
<pre class="hCode">
&lt;svg style="width: 400px; height: 120px; border: 1px solid gray;"&gt;
        &lt;circle cx="40" cy="60" r="30" fill="green"&gt;
                &lt;animate
                        <span class="rred">id</span>="hMove"
                        <span class="rred">attributeName</span>="cx"
                        <span class="rred">begin</span>="click"
                        <span class="rred">from</span>="40"
                        <span class="rred">to</span>="360"
                        <span class="rred">dur</span>="2"
                        <span class="rred">repeatCount</span>="1"
                        <span class="rred">fill</span>="freeze"
                        <span class="rred">restart</span>="whenNotActive"
                /&gt;
        &lt;/circle&gt;
&lt;/svg&gt;
</pre>

        <svg style="width: 400px; height: 120px; border: 1px solid gray;">
                <circle cx="40" cy="60" r="30" fill="green">
                        <animate id="hMove" attributeName="cx" begin="click" from="40" to="360" dur="2" repeatCount="1" fill="freeze" restart="whenNotActive" />
                </circle>
        </svg>

        <p>【说明】单击上方的绿色小圆,会触发 animate 动画,后续单击会继续触发。</p>
<p>现在,我们来逐一理解 animate 动画的各个参数:</p>

<pre class="hCode">
<span class="rred">id</span> : 和HTML一样,svg元素也可以有自己的id标识,animate的id标识用于后续JS控制的句柄,本例,它是多余的
<span class="rred">attributeName</span> : 动画要改变的宿主元素(本例为circle)的属性名称
<span class="rred">begin</span> : 动画什么时候或以何种状态开始,值可为 2s 之类,表示两秒后开始,本例使用 click,表示点击后开始
<span class="rred">from</span> : 动画从哪儿或什么状态开始,宿主元素有初始属性值时可以省略
<span class="rred">to</span> : 动画在哪儿或什么状态结束,不能省略
<span class="rred">dur</span> : 就是 duration,动画一个运行周期所用的时间,单位缺省时是秒即 s,可以使用其他单位,如 m、ms
<span class="rred">repeatCount</span> : 动画重复次数,无限循环值用 indefinite(CSS用infinite)
<span class="rred">fill</span> : 动画结束时的状态,值为 freeze(冻结)表示停留在结束时的状态,默认值 remove 或缺省fill属性时回到初始状态
<span class="rred">restart</span> : 动画重启方式,always=任何时候都可以重启、whenNotActive=非活动状态可以重启、never=不能重启
</pre>

<p>animate 每一次使用改变一个宿主元素属性值,如果希望同时改变其他属性值,那么,再加一个或多个 animate 标签。下例,在小圆移动的同时,将圆的填充色从 green 变为 red,期间的颜色变化,基于 green 到 red 的色相转换。单击绿色小圆看看效果:</p>

        <svg style="width: 400px; height: 120px; border: 1px solid gray;">
                <circle cx="40" cy="60" r="30" fill="green">
                        <animate attributeName="cx" begin="click" from="40" to="360" dur="2" repeatCount="1" fill="freeze" />
                        <animate attributeName="fill" begin="click" to="red" dur="2" repeatCount="1" fill="freeze"
                        />
                </circle>
        </svg>

        <p>代码如下:</p>

<pre class="hCode">
&lt;svg style="width: 400px; height: 120px; border: 1px solid gray;"&gt;
        &lt;circle cx="40" cy="60" r="30" fill="green"&gt;
                &lt;animate attributeName="cx" begin="click" from="40" to="360" dur="2" repeatCount="1" fill="freeze" /&gt;
                &lt;animate attributeName="fill" begin="click" to="red" dur="2" repeatCount="1" fill="freeze" /&gt;
        &lt;/circle&gt;
&lt;/svg&gt;
</pre>

<p>animate 的参数from 和 to 可以用 values 替代。values 参数可能更为灵活,比方说,我们想让小圆左右来回移动,且颜色在红蓝绿之间来回变换,那么,values 参数可以解决问题。下面是代码和效果,注意 repeatCount 的设置以及 values 值的设定方式:</p>

<pre class="hCode">
&lt;svg style="width: 400px; height: 120px; border: 1px solid gray;"&gt;
        &lt;circle cx="40" cy="60" r="30" fill="green"&gt;
                &lt;animate attributeName="cx" begin="click" values="40; 360; 40" dur="4" repeatCount="indefinite" /&gt;
                &lt;animate attributeName="fill" begin="click" values="red; blue; green"; dur="3" repeatCount="indefinite" /&gt;
        &lt;/circle&gt;
&lt;/svg&gt;
</pre>

<p>单击绿色小圆启动动画:</p>

        <svg id="mysvg" style="width: 400px; height: 120px; border: 1px solid gray;">
                <circle id="mycc" cx="40" cy="60" r="30" fill="green">
                        <animate id="ani1" attributeName="cx" begin="click" values="40; 360; 40" dur="4" repeatCount="indefinite" />
                        <animate id="ani2" attributeName="fill" begin="click" values="red;blue;green"; dur="3" repeatCount="indefinite" />
                </circle>
        </svg>

<p><input id="stopAni" type="button" value="停止动画" /></p>

<p>至于 animate 的简化版本,set 动画,它缩减了 animate 的属性,只运行一次动画,可操作空间极少。看下面的代码:</p>

<pre class="hCode">
&lt;svg style="width: 400px; height: 120px; border: 1px solid gray;"&gt;
        &lt;circle cx="40" cy="60" r="30" fill="green"&gt;
                &lt;set attributeName="fill" begin="3s" to="red" /&gt;
        &lt;/circle&gt;
&lt;/svg&gt;
</pre>

<p>上述代码,set 标签要改变的宿主元素的属性是fill(填充色),3秒钟后小圆变为红色。可以将代码放到 <a href="http://mhh.52qingyin.cn/api/pcode/" target="_blank">pencil code</a> 运行看看效果。</p>

<p>【小结】animate 动画需要将 animate 标签放在运行动画的元素标签里面,参数繁多(本示例尚未全部使用),但都是语义化的,很容易理解。每一个animate标签只能改变宿主元素的一个属性,可以并列使用以改变多个属性。set 动画可视为是 animate 动画的简化版,它只运行一次。</p>

<p>请特别注意,本节所介绍的svg动画的代码构成和所提到的 animate 动画参数,像 attributeName、begin、from、to、value、dur、repeatCount、fill 等等,其它的动画元素同样会用到,所以本节既介绍 animate 动画,也是其它动画的基础。</p>

</div>

<script>

let hCodes = document.querySelectorAll('.hCode');

hCodes.forEach((item,key) => {
        let lines = hCodes.innerText.trim().split('\n').length;
        let str = '';
        for(let i = 0; i < lines; i ++) {
                str += i + 1 + '\n';
        }
        item.dataset.line = str;
});

stopAni.onclick = () => mysvg.pauseAnimations();

mysvg.onclick = () => mysvg.unpauseAnimations();

</script>

红影 发表于 2023-11-19 10:38

这个里面的设置难不难,但语句还挺多,需要好好记一下呢{:4_187:}

红影 发表于 2023-11-19 10:38

这个讲解非常细致入微,黑黑辛苦了{:4_199:}

马黑黑 发表于 2023-11-19 11:38

红影 发表于 2023-11-19 10:38
这个里面的设置难不难,但语句还挺多,需要好好记一下呢

初中英语学得好,记起属性呱呱叫{:4_170:}

马黑黑 发表于 2023-11-19 11:38

红影 发表于 2023-11-19 10:38
这个讲解非常细致入微,黑黑辛苦了

谢茶

醉美水芙蓉 发表于 2023-11-19 16:20

马黑黑 发表于 2023-11-19 19:34

醉美水芙蓉 发表于 2023-11-19 16:20
黑黑老师辛苦了!

{:4_190:}

红影 发表于 2023-11-19 22:17

马黑黑 发表于 2023-11-19 11:38
初中英语学得好,记起属性呱呱叫

初中离现在挺远,还得重新记一下才好{:4_173:}

红影 发表于 2023-11-19 22:21

马黑黑 发表于 2023-11-19 11:38
谢茶

这个里面已经有个id名了,还要有个attributeName名,这个挺费解。

马黑黑 发表于 2023-11-19 23:21

红影 发表于 2023-11-19 22:17
初中离现在挺远,还得重新记一下才好

持久性记忆应该是有的额

马黑黑 发表于 2023-11-19 23:22

本帖最后由 马黑黑 于 2023-11-19 23:27 编辑

红影 发表于 2023-11-19 22:21
这个里面已经有个id名了,还要有个attributeName名,这个挺费解。
attributeName 指定要变化的运动对象的属性名,比如半径 r,圆心 {cx,cy} 中的一个,矩形的 xy 坐标中的一个,等等;id不一样,分离式动画依靠 id 来识别运动针对哪一个

红影 发表于 2023-11-20 16:07

马黑黑 发表于 2023-11-19 23:21
持久性记忆应该是有的额

那玩意又不用,怎么会记得啊{:4_173:}

红影 发表于 2023-11-20 16:08

马黑黑 发表于 2023-11-19 23:22
attributeName 指定要变化的运动对象的属性名,比如半径 r,圆心 {cx,cy} 中的一个,矩形的 xy 坐标中的 ...

嗯嗯,知道了,若没指定属性,那就不知道要变化的是什么了。现在清楚了{:4_187:}

马黑黑 发表于 2023-11-20 19:21

红影 发表于 2023-11-20 16:08
嗯嗯,知道了,若没指定属性,那就不知道要变化的是什么了。现在清楚了

应该从一开始介绍就清楚才对{:4_189:}

马黑黑 发表于 2023-11-20 19:22

红影 发表于 2023-11-20 16:07
那玩意又不用,怎么会记得啊

会的会的,比如好肚油肚

红影 发表于 2023-11-20 19:58

马黑黑 发表于 2023-11-20 19:21
应该从一开始介绍就清楚才对

脑筋别住了一下下,现在顺了{:4_173:}

红影 发表于 2023-11-20 20:01

马黑黑 发表于 2023-11-20 19:22
会的会的,比如好肚油肚

问题字母语言都有点接近的,我后来学的德语,职称时的外语考试还选了德语,因为小语种更好考。现在两种语都不会了,只会汉语{:4_173:}

马黑黑 发表于 2023-11-20 22:40

红影 发表于 2023-11-20 20:01
问题字母语言都有点接近的,我后来学的德语,职称时的外语考试还选了德语,因为小语种更好考。现在两种语 ...

汉语天下第一

红影 发表于 2023-11-21 11:07

马黑黑 发表于 2023-11-20 22:40
汉语天下第一

那是必须的,以后万国来朝,都必须学汉语{:4_173:}

马黑黑 发表于 2023-11-21 12:13

红影 发表于 2023-11-21 11:07
那是必须的,以后万国来朝,都必须学汉语

等着
页: [1] 2
查看完整版本: svg动画之 animate(一)