o'Reill的SVG精髓(第二版)学习笔记——第十二章

第十二章 SVG动画

12.1动画基础

SVG的动画特性基于万维网联盟的“同步多媒体集成语言”(SMIL)规范(http://www.w3.org/TR/SMIL3)。

在这个动画系统中,我们可以指定想要进行动画的属性(比如颜色、动作或者变形属性)的起始值和结束值,以及动画的开始时间和持续时间。

http://oreillymedia.github.io/svg-essentials-examples/ch12/simple_animation.html

<!-- 收缩矩形 -->  
  <svg width="500" height="500" viewBox="0 0 500 500">
<rect x="10" y="10" width="200" height="20" stroke="black" fill="none">
<animate attributeName="width" attributeType="XML" from="200" to="20" begin="0s" dur="5s" fill="freeze" />
</rect>
</svg>

<rect>元素不再是一个空元素,它里面包含了公话元素。

<animate>元素指定下列信息。

①attributeName:动画中应该持续改变的值。

②attributeType。width属性是一个XML属性。另一个常用的attributeType的值是CSS。表示我们想要改变的属性是一个CSS属性。如果忽略这一属性,它的默认值是auto。它首先会搜索CSS属性,然后才是XML属性。

③属性的起始(from)和结束(to)值。from值是可选的,如果不指定它,则会使用父元素的值。此外,还有一个by属性,可以代替to,它时一个从from值开始的偏移量;动画结束时属性的值为结束值。

④动画的开始时间和持续时间。这个例子中,时间以秒为单位,通过在数字后面使用s指定。

⑤动画结束时做什么,这个例子中,持续5秒以后,属性会“冻结(freeze)”为to值,也就是SMIL fill属性,它会告诉动画引擎如何填补剩下的时间。如果我们移除这一行,会使用默认值(remove),5秒的动画完成之后width属性会返回它的原始值200。

下例,从一个20*20的绿色方块开始,将在8秒时间里增长为250*200。前3秒,绿色的透明度会增加,接下来的3秒会减小。注意fill-opacity是使用attributeType=“CSS”的,因为它设置在style属性中。

http://oreillymedia.github.io/svg-essentials-examples/ch12/multiple_animation.html

<!-- 单个对象上的多重动画 -->
<svg width="500" height="500" viewBox="0 0 500 500">
<rect x="10" y="10" width="20" height="20" style="stroke:black;fill:green;style:fill-opacity:0.25;">
<animate attributeName="width" attributeType="XML" from="20" to="200" begin="0s" dur="8s" fill="freeze" />
<animate attributeName="height" attributeType="XML" from="20" to="150" begin="0s" dur="8s" fill="freeze" />
<animate attributeName="fill-opacity" attributeType="CSS" from="0.25" to="1" begin="0s" dur="3s" fill="freeze" />
<animate attributeName="fill-opacity" attributeType="CSS" from="1" to="0.25" begin="3s" dur="3s" fill="freeze" />
</rect>
</svg>

下例是一个正方形和圆形动画。正方形尺寸会在8秒的时间里从20*20扩大到120*120.动画开始2秒之后,圆形的半径在4秒的时间里从20扩大到50。

http://oreillymedia.github.io/svg-essentials-examples/ch12/multiple_animation2.html

<!-- 多个对象的简单动画 -->
<svg width="500" height="500" viewBox="0 0 500 500">
<rect x="10" y="10" width="20" height="20" style="stroke:black;fill:#cfc;">
<animate attributeName="width" attributeType="XML" begin="0s" dur="8s" from="20" to="120" fill="freeze" />
<animate attributeName="height" attributeType="XML" begin="0s" dur="8s" from="20" to="120" fill="freeze" />
</rect>
<circle cx="70" cy="70" r="20" style="fill:#ccf;stroke:black;">
<animate attributeName="r" attributeType="XML" begin="2s" dur="4s" from="20" to="50" fill="freeze" />
</circle>
</svg>

12.2 动画时间详解

SCG动画用到的动画时钟在SVG加载完成时开始启动计时,当用户离开页面时停止计时。我们可以以下列任意一种方式指定特定动画的开始和持续时间为一个数值。

①时、分、秒形式(1:20:33)的完整时间值

②分、秒形式(02:15)的局部时间值。

③以h(时)、min(分)、s(秒)或者ms(毫秒)缩写结尾的时间值,比如dur=“3.5s” begin=“1min”。不可以在值和单位之间插入任何空白。

如果不指定单位,则默认为秒。

12.3 同步动画。

我们可以绑定动画的开始时间为另一个动画的开始或者结束,而不是在文档加载时定义每个动画的开始时间。

下例中有两个圆的动画,第二个会在第一个停止缩放时开始扩大。

<!-- 同步动画 -->
<svg width="500px" height="500px" viewBox="0 0 500 500">
<circle cx="60" cy="60" r="30" style="fill:#f9f;stroke:gray;">
<animate id="c1" attributeName="r" attributeType="XML" begin="0s" dur="4s" from="30" to="10" fill="freeze" />
</circle> <circle cx="120" cy="60" r="10" style="fill:#9f9;stroke:gray;">
<animate attributeName="r" attributeType="XML" begin="c1.end" dur="4s" from="10" to="30" fill="freeze" />
</circle>
</svg>

我们还可以给同步添加一个偏移量。要让一个动画在另一个动画开始2秒后再开始,我们要使用类似begin=“otherAnim.end+2s”的形式指定(可以在加号两侧添加空白),下例中,第二个圆会在第一个圆开始收缩1.25秒之后开始增长。

<!-- 带有偏移量的同步动画 -->
<svg width="500px" height="500px" viewBox="0 0 500 500">
<circle cx="60" cy="60" r="30" style="fill:#f9f;stroke:gray;">
<animate id="c1" attributeName="r" attributeType="XML" begin="0s" dur="4s" from="30" to="10" fill="freeze" />
</circle> <circle cx="120" cy="60" r="10" style="fill:#9f9;stroke:gray;">
<animate attributeName="r" attributeType="XML" begin="c1.begin+1.25s" dur="4s" from="10" to="30" fill="freeze" />
</circle>
</svg>

end属性:它可以给动画设置一个结束时间,但这并不能代替dur属性!

下例中动画会在页面载入6秒之后开始。它会持续12秒或者知道名为otherAnim的动画结束,这取决于动画先结束还是12秒先到:

<animate attributeName="width" attributeType="XML" begin="6s" dur="12s" end="otherAnim.end" from="10" to="100" fill="freeze" />

我们也可以设置end的值为一个指定的时间;这可以用于在中途拦截动画,这样我们就可以看看是否一切都在正确的位置。

下面这个动画在5秒时开始,并且应该持续10秒,但是会在文档载入后9秒(动画开始4秒后)暂停。这个动画会停止在40%处,因此宽度会冻结在140(从100到200的40%的距离)

<animate attributeName="width" attributeType="XML" begin="5s" dur="10s" end="9s" from="100" to="200" fill="freeze" />

12.4 重复动作

动画只发生一次,fill被设置为freeze使动画保持在最后阶段。如果想要对象返回到动画起始状态,忽略这个属性即可(等价于设置fill为默认值remove)

另外两个属性允许重复动画

第一个是repeatCount,设置一个整型值,告诉引擎我们需要将制定动画重复多少次。

第二个是repeatDur,设置一个值,告诉引擎应该持续多少时间。

如果想要动画重复到用户离开页面。设置repeatCount或者repeatDur的值为indefinite即可。通常我们只需要一个,而不是两个都使用。

如果两个同时指定,则哪个属性指定的时间先到达就使用哪个属性。

下例中的动画展示了两个圆形。上面的圆从左侧移到右侧,重复2次,每次5秒。第二个圆从右侧移动到左侧,总共持续8秒。

http://oreillymedia.github.io/svg-essentials-examples/ch12/repeated_action.html

<!-- 重复动画示例 -->
<svg width="500px" height="500px" viewBox="0 0 500 500">
<circle cx="60" cy="60" r="30" style="fill:none;stroke:red;">
<animate attributeName="cx" attributeType="XML" begin="0s" dur="5s" repeatCount="2" from="60" to="260" fill="freeze" />
</circle> <circle cx="260" cy="90" r="30" style="fill:#ccf;stroke:black;">
<animate attributeName="cx" attributeType="XML" begin="0s" dur="5s" repeatDur="8s" from="260" to="60" fill="freeze" />
</circle>
</svg>

我们也可以将某个动画的开始时间绑定到另一个重复动画的第指定次数动画开始时间。这样的话,需要给第一个动画一个id,然后设置第二个动画的begin为id.repeat(count),count是第一个动画的重复次数,以0开始。

下例中展示了上面的圆从左侧移到右侧三次,每次重复需要5秒。下面的正方形会从右侧移到左侧一次。但是直到上面的圆重复第二次之后2.5秒才开始。

<!-- 带重复的同步动画 -->
<svg width="500px" height="500px" viewBox="0 0 500 500">
<circle cx="60" cy="60" r="15" style="fill:none;stroke:red;">
<animate id="circleAnim" attributeName="cx" attributeType="XML" begin="0s" dur="5s" repeatCount="3" from="60" to="260" fill="freeze" />
</circle> <rect x="230" y="80" width="30" height="30" style="fill:#ccf;stroke: black;">
<animate attributeName="x" attributeType="XML" begin="circleAnim.repeat(1)+2.5s" dur="5s" from="230" to="30" fill="freeze" />
</rect>
</svg>

12.5 对复杂的属性应用动画

动画并不仅限于简单的数值和长度。我们可以为几乎任何属性和样式应用动画,使这些属性在两个值之间平滑过渡。

要为颜色应用动画,只需要给from和to属性应用有效的颜色即可,颜色被看做是用于计算的三个数值分量:R、G、B的每个值都会从一个颜色转换到另一个。

下例为原型的填充和笔画颜色应用了动画,填充色从淡黄色改变为红色,轮廓从灰色改变为蓝色。这两个动画都是在页面载入2秒之后开始。

http://oreillymedia.github.io/svg-essentials-examples/ch12/animate_color.html

<!-- 颜色动画示例 -->
<svg width="500px" height="500px" viewBox="0 0 500 500">
<circle cx="60" cy="60" r="35" style="fill:#ff9;stroke:gray;stroke-width:10;">
<animate attributeName="fill" begin="2s" dur="4s" from="#ff9" to="red" fill="freeze" />
<animate attributeName="stroke" begin="2s" dur="4s" from="gray" to="blue" fill="freeze" />
</circle>
</svg>

我们还可以为值为数字列表的属性应用动画,只要列表中数字的数量没有改变即可;列表中的每个值都是单独变换的。这意味着我们可以为路径数据或者多边形的点应用动画。只要我们维持点的数量和路径片段的类型即可。

下例展示了一个<polygon>和一个<path>动画

http://oreillymedia.github.io/svg-essentials-examples/ch12/animate_path_poly.html

<!-- 路径和多边形动画示例 -->
<svg width="500px" height="500px" viewBox="0 0 500 500">
<polygon points="30 30 70 30 90 70 10 70" style="fill:#fcc;stroke:black;">
<animate id="animation" attributeName="points" attributeType="XML" to="50 30 70 50 50 90 30 50" begin="0s" dur="5s" fill="freeze" />
</polygon> <path d="M15 50 Q 40 15,50 50,65 32,100 40" style="fill:none;stroke:black;" transform="translate(0,50)">
<animate attributeName="d" attributeType="XML" to="M50 15 Q 15 40,50 50,32 65,40 100" begin="0s" dur="5s" fill="freeze" />
</path>
</svg>

12.6 指定多个值

我们还可以给动画提供一个特定的中间值,从而允许用一个独立的<animate>元素定义复杂的变化序列。我们可以提供一个分号分隔的,动画在持续时间内使用的值列表。

下例展示了一个使用淡黄色、淡蓝色、粉红色以及淡绿色值动画绘制颜色的圆。

http://oreillymedia.github.io/svg-essentials-examples/ch12/animating_values.html

<!-- 使用特定的值动画绘制颜色 -->
<svg width="500px" height="500px" viewBox="0 0 500 500">
<circle cx="50" cy="50" r="30" style="fill:#ff9;stroke:black;">
<animate attributeName="fill" begin="2s" dur="4s" values="#ff9;#99f;#f99;#9f9;" fill="freeze" />
</circle>
</svg>

values属性也可以用来实现交替来回的重复动画,即从起始值到结束值再回到起始值,使用values=“start;end;start;”形式即可

12.7 多级动画时间。

当一个动画有多个值的时候,动画的持续时间(dur属性)就是要一次通过所有值的时间,默认情况下,动画的持续时间被划分为每个过渡周期等长的片段。上例使用了四个值,因此有三个颜色过渡;总的持续时间为4秒,因此每个过渡持续4/3秒。

keyTimes属性允许我们以其他方式划分持续时间。keyTimes的格式也是一个分号分隔的列表,但它必须有和values相同数目的条目。第一个条目始终为0,最后一个始终为1;中间时间使用0到1之间的小数表示,代表动画的持续时间比例,当动画到达某个值的时候刚好对应相应的时间值。

对时间的更多控制可以通过calcMode属性完成。calcMode有一下四种可能的值。

①paced:SVG阅读器会计算后续各个值之间的间隔,并以此为一句划分持续时间,因此其变化的速度是恒定的(keyTimes属性会被忽略)。适用于颜色、简单的数值或者偿付,但不能用于点列表或者路径数据。

②linear:<animate>元素的默认行为,每个过渡内的速度是恒定的,但是分配给每个过渡的时长是此昂等的(如果没有指定keyTimes)或者由keyTImes决定。

③discrete:动画会从一个值跳到另一个值,但没有过渡。如果动画绘制一个不支持过渡的属性(比如font-family),会自动使用该模式。

④spline:动画会按照keySplines属性加速或者减速;

12.8<set>元素

对于非数字属性或者不能过渡的属性,我们可能想要在动画序列的某个点上改变某个值。

比如我们可能想要一个初始不可见的文本项,使它在某个时间变得可见,这里并不需要from和to,因此,SVG引入了方便速记的<set>元素,它只需要一个to属性以及适当的时间信息。

http://oreillymedia.github.io/svg-essentials-examples/ch12/animation_set.html

<!-- <set>元素示例 -->
<svg width="500px" height="500px" viewBox="0 0 500 500">
<circle cx="60" cy="60" r="30" style="fill:#ff9;stroke:gray;">
<animate id="c1" attributeName="r" sttributeType="XML" begin="0s" dur="4s" from="30" to="0" fill="freeze" />
</circle>
<text text-anchor="middle" x="60" y="60" style="visibility:hidden;">
<set attributeName="visibility" attributeType="CSS" to="visible" begin="4.5s" dur="1s" fill="freeze"/>
All gone!
</text>
</svg>

12.9<animateTransform>元素

<animte>元素并不适用于旋转、平移、缩放或者倾斜变换。因为它们都被包裹在transform属性内。<animateTransform>元素可以解决这个问题。

我们可以设置它的attributeName为transform。然后用type属性的值指定变换的哪个值应该变化(translate、scale、rotate、skewX或者skewY之一)。from和to的值指定为适当的要动画绘制的变换。

下例把矩形在水平方向上由正常的比例拉伸了四倍,垂直方向上拉伸了两倍。

注意矩形是围绕原点的,因此它的缩放时并不会移动;而它在一个<g>元素内,因此它可以被平移到更适当的地方

http://oreillymedia.github.io/svg-essentials-examples/ch12/animate_transform.html

<!-- <animateTransform>元素示例 -->
<svg width="200" height="100">
<g transform="translate(100,60)">
<rect x="-10" y="-10" width="20" height="20" style="fill:#ff9;stroke:black;">
<animateTransform attributeType="XML" attributeName="transform" type="scale" from="1" to="4 2" begin="0s" dur="4s" fill="freeze"/>
</rect>
</g>
</svg>

如果打算为多个变换应用动画,必须使用additive属性。additive的默认值是replace,它会替换动画的指定变换。通过设置additive为sum,SCG会积累变换。

http://oreillymedia.github.io/svg-essentials-examples/ch12/additive_transform.html

<!-- 多个<animateTransform>元素示例 -->
<svg width="200" height="100">
<g transform="translate(100,60)">
<rect x="-10" y="-10" width="20" height="20" style="fill:#ff9;stroke:black;">
<animateTransform attributeName="transform" attributeType="XML" type="scale" from="1" to="4 2" additive="sum" begin="0s" dur="4s" fill="freeze" />
<animateTransform attributeName="transform" attributeType="XML" type="rotate" from="0" to="45" additive="sum" begin="0s" dur="4s" fill="feeze" />
</rect>
</g>
</svg>

12.10 <animateMotion>元素

我们可以通过在<animateTransform>元素中使用translate让对象沿着一条直线路径运动,然而,如果想要对象按照更复杂的路径运动,我们需要一系列变换动画定时一个接一个地执行。<animateMotion>元素使得让对象沿着任意路径运动变得容易。

如果想要对直线运动使用<animateMotion>,简单的设置from和to属性,然后给每个属性分配一对(x,y)坐标即可。这个坐标用于指定要移动形状的坐标系统中(0,0)点的位置。类似于translate(x,y)的工作原理。

下例展示了将一组圆和矩形从(0,0)移动到(60,30):

http://oreillymedia.github.io/svg-essentials-examples/ch12/linear_animateMotion.html

<!-- 线性路径动画 -->
<svg width="200" height="100">
<g>
<rect x="0" y="0" width="30" height="30" style="fill:#ccc;" />
<circle cx="30" cy="30" r="15" style="fill:#cfc;stroke:green;" />
<animateMotion from="0,0" to="60,30" dur="4s" fil="freeze" / >
</g>
</svg>

如果想要更复杂的路径运动,要使用path属性,它的值与<path>元素的d属性的值格式相同:

http://oreillymedia.github.io/svg-essentials-examples/ch12/complex_animate_motion.html

<!-- 沿复杂的路径运动 -->
<svg width="250" height="250">
<!-- 要移动的三角路径 -->
<path d="M50,125 C 100,25 150,225,200,125" style="fill:none;stroke:blue" />
<!-- 三角形会沿着运动路径运动。路径原点与三角形底边中点垂直对齐 -->
<path d="M-10,-3 L10,-3 L0,-25z" style="fill:yellow;stroke:red;">
<animateMotion path="M50,125 C100,25 150,225,200,125" dur="6s" fill="freeze" />
</path>
</svg>

如果希望对象倾斜以使其x轴始终平行于路径的方向,只要给<animateMotion>元素添加一个值为auto的rotate属性即可。

http://oreillymedia.github.io/svg-essentials-examples/ch12/animate_motion_rotate.html

<!-- 带自动旋转的复杂路径动画 -->
<svg width="250" height="250">
<!-- 要移动的三角路径 -->
<path d="M50,125 C 100,25 150,225,200,125" style="fill:none;stroke:blue" />
<!-- 三角形会沿着运动路径运动。它通过在原点上方垂直方向上与三角形底边中心水平对齐的方式定义 -->
<path d="M-10,-3 L10,-3 L0,-25z" style="fill:yellow;stroke:red;">
<animateMotion path="M50,125 C100,25 150,225,200,125" rotate="auto" dur="6s" fill="freeze" />
</path>
</svg>

当我们不使用rotate属性时,其默认值是0,此时对象就像一个沿着路径浮动的热气球,如果设置rotate为auto,对象就想坐过山车一样,沿着路径向上或向下倾斜。

我们也可以为rotate设置一个数值,这会使对象在动画中旋转。

<!-- 使用<mpath>定义沿着复杂路径运动的动画 -->
<svg width="250" height="250">
<!-- 要移动的三角路径 -->
<path id="cubicCurve" d="M50,125 C 100,25 150,225,200,125" style="fill:none;stroke:blue" />
<!-- 三角形会沿着运动路径运动。它通过在原点上方垂直方向上与三角形底边中心水平对齐的方式定义 -->
<path d="M-10,-3 L10,-3 L0,-25z" style="fill:yellow;stroke:red;">
<animateMotion rotate="auto" dur="6s" fill="freeze">
<mpath xlink:href="#cubicCurve">
</animateMotion>
</path>
</svg>

12.11 为运动指定关键点和时间

匀速动画使<animateMotion>的默认行为(等价于calcMode=“paced”);后续移动之间需要花费的时间与它们之间的距离成正比。

我们可以针对运动动画使用keyTimes,但是如果我们使用路径而不是value列表定义运动,那么需要针对路径使用keyPoints属性指定关键点。

keyPoints是一个分号分隔的十进制数值列表。每个点表示对象应该按照keyTimes列表中对应的时间点沿着路径移动多远。正如keyTimes的范围是从0到1。keyPoints的也是从0到1.

keyPoints可以在路径的中间开始或者结束,还可以向两个方向运动。然而,keyPoints和keyTimes列表必须拥有相同数量的条目,并且我们必须设置calcMode=“linear”(或者spline)

http://oreillymedia.github.io/svg-essentials-examples/ch12/key_points.html

<!-- 使用keyPoints和keyTimes沿着路径做变速运动 -->
<svg width="250" height="250">
<!-- 要移动的三角路径 -->
<path id="cubicCurve" d="M50,125 C 100,25 150,225,200,125" style="fill:none;stroke:blue" />
<!-- 三角形会沿着运动路径运动。它通过在原点上方垂直方向上与三角形底边中心水平对齐的方式定义 -->
<path d="M-10,-3 L10,-3 L0,-25z" style="fill:yellow;stroke:red;">
<animateMotion path="M50,125 C 100,25 150,225,200,125" rotate="auto" keyPoints="0;0.2;0.8;1" keyTimes="0;0.33;0.66;1" calcMode="linear" dur="6s" fill="freeze">
</path>
</svg>

12.12 使用CSS处理SVG动画

第一步:选中想要运动的元素,然后设置将动画属性作为一个整体进行设置。

第二步:告诉浏览器改变选中元素的哪个属性以及在动画的什么阶段;这些都定义在@keyframes说明符中。

12.12.1动画属性:

①animation-name就是@keyframes 说明符的名称

②animation-duration决定动画应该持续多久;它的值是数字后面紧跟一个时间单位。

③animation-timing-function告诉浏览器如何计算中间值。

④animation-iteration-count告诉浏览器重复动画多少次,infinite表示无限循环,

⑤animation-direction 决定动画使反向还是正向执行,以及是否在两个值之间交替。

⑥animation-play-state可以设置为running或者paused

⑦animation-delay告诉浏览器应用样式之后等待多久开始动画。

⑧animation-fill-mode告诉动画不在执行时使用什么属性。可以是forwards(应用动画结束时的属性值)、backward(应用动画开始时的属性值)或者both。

/* 使用CSS设置动画 */
.starStyle {
animation-name:starAnim;
animation-duration:2s;
animation-iteration-count:;
animation-direction: alternate;
animation-timing-function:ease;
animation-play-state:running;
}

12.12.2 设置动画关键帧

我们可以通过使用@keyframes 这一媒体类型设置动画每个阶段要改变的属性,后面紧跟一个控制动画的名称。

在@keyframes内,我们要列出keyframe选择器。即告诉浏览器何时改变属性的百分比。对于每个选择器,我们要留出动画应该呈现的属性和值。对于基于Webit的浏览器,请使用@-webkit-keyfranmes

http://oreillymedia.github.io/svg-essentials-examples/ch12/svg_css.html

http://oreillymedia.github.io/svg-essentials-examples/ch12/svg_css_anim1.html

<style>
/* 使用CSS设置动画 */
#star {
animation-name:starAnim;
animation-duration:2s;
animation-iteration-count: 4;
animation-direction: alternate;
animation-timing-function:ease-in-out;
animation-transition:linear;
}
@keyframes starAnim{
0%{
fill-opacity:1.0;
stroke-width:0;
}
100%{
fill-opacity:0;
stroke-width:6;
}
}
</style> <!-- CSS关键帧规范 -->
<svg id="game" width="450" height="450" viewBox="0 0 450 450">
<defs>
<g id="starDef">
<path d="M 38.042 -12.361 9.405 -12.944 -0.000 -40.000 -9.405 -12.944 -38.042 -12.361 -15.217 4.944 -23.511 32.361 0.000 16.000 23.511 32.361 15.217 4.944 Z">
</g>
</defs>
<use id="star" xlink:href="#starDef" style="transform:translate(225px,225px) rotate(0deg);fill:#ff0000;stroke:#ff0000;">
</svg>

12.12.3 CSS中的动画运动

如果使用纯CSS处理动画运动,我们不能使用transform属性。相反,必须使用CSS样式平移、旋转和缩放SVG。

如果想要将SVG元素平移到(100,50),缩放1.5倍,然后旋转90°:

transform:translate(100px,50px) scale(1.5) rotate(90deg)

下例让星星向上移动并旋转,然后降落到起点所需要的关键帧,由于100%关键帧没有指定translate,星星会回到它的原始位置。这也是除了20%关键帧,50%和80%关键帧必须指定translate的原因,有了它,星星在该部分动画期间才不会垂直移动。

http://oreillymedia.github.io/svg-essentials-examples/ch12/svg_css_anim2.html

<style>
/* 使用CSS设置动画 */
#star {
animation-name:starAnim;
animation-duration:2s;
animation-iteration-count: 4;
animation-direction: alternate;
animation-timing-function:ease-in-out;
animation-transition:linear;
}
@keyframes starAnim{
0%{
fill-opacity:1.0;
stroke-width:0;
}
20%{
transform:translate(100px,50px);
}
50%{
transform:translate(100px,50px) rotate(180deg);
}
80%{
transform:translate(100px,50px) rotate(360deg);
}
100%{
fill-opacity:0;
stroke-width:6;
}
}
</style> <!-- CSS关键帧规范 -->
<svg id="game" width="450" height="450" viewBox="0 0 450 450">
<defs>
<g id="starDef">
<path d="M 38.042 -12.361 9.405 -12.944 -0.000 -40.000 -9.405 -12.944 -38.042 -12.361 -15.217 4.944 -23.511 32.361 0.000 16.000 23.511 32.361 15.217 4.944 Z">
</g>
</defs>
<use id="star" xlink:href="#starDef" style="transform:translate(225px,225px) rotate(0deg);fill:#ff0000;stroke:#ff0000;">
</svg>

<!-- 多个<animateTransform>元素示例 -->
    <svg width="200" height="100">
        <g transform="translate(100,60)">
            <rect x="-10" y="-10" width="20" height="20" style="fill:#ff9;stroke:black;">
                <animateTransform attributeName="transform" attributeType="XML" type="scale" from="1" to="4 2" additive="sum" begin="0s" dur="4s" fill="freeze" />
                <animateTransform attributeName="transform" attributeType="XML" type="rotate" from="0" to="45" additive="sum" begin="0s" dur="4s" fill="feeze" />
            </rect>
        </g>
    </svg>

上一篇:十二. Go并发编程--sync/errGroup


下一篇:CSAPP:第十二章 并发编程