SVG动画
有多种不同的方法可以为SVG图片中的图形添加动画。在本文中,我将介绍各种可能的动画。
SVG动画示例
下面是一个简单的SVG动画例子:
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<rect x="10" y="10" height="110" width="110"
style="stroke:#ff0000; fill: #0000ff">
<animateTransform
attributeName="transform"
begin="0s"
dur="20s"
type="rotate"
from="0 60 60"
to="360 60 60"
repeatCount="indefinite"
/>
</rect>
</svg><svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<rect x="10" y="10" height="110" width="110"
style="stroke:#ff0000; fill: #0000ff">
<animateTransform
attributeName="transform"
begin="0s"
dur="20s"
type="rotate"
from="0 60 60"
to="360 60 60"
repeatCount="indefinite"
/>
</rect>
</svg>请注意,在<rect>元素内嵌套了一个<animateTransform>元素。正是这个元素为矩形添加了动画。
最终的SVG动画如下:
动画选项概述
动画就是根据时间的推移操作图形的属性。通过下面5个SVG动画元素中的一个或多个可以实现。
<set><animate><animateColor><animateTransform><animateMotion>
每一个SVG动画元素都为SVG图形的不同方面添加设置或动画。本文的后续部分将对这些动画元素作详细描述。
set
set是SVG动画中最简单的元素。它只是在特定时间间隔过去后将属性设置为某个值。因此,形状的动画不是连续的,而是只改变属性值一次。
下面是一个<set>元素例子:
<circle cx="30" cy="30" r="25" style="stroke: none; fill: #0000ff;">
<set attributeName="r" attributeType="XML"
to="100"
begin="5s" />
</circle><circle cx="30" cy="30" r="25" style="stroke: none; fill: #0000ff;">
<set attributeName="r" attributeType="XML"
to="100"
begin="5s" />
</circle>可以发现,<set>元素嵌套在circle元素内。这就是<set>元素应用到图形的方法——将其嵌套在SVG图形内部。
<set>元素在特定时间设置属性的值,要设置的属性的名称在attributeName属性中指定。在to属性中指定将为其设置的值,设置属性值的时间在begin属性中指定。
上面的例子在5秒后将属性r设置为100,最终图片如下:
attributeType
上述例子的<set>元素中还有一个值为XML的attributeType属性。这是因为在示例中设置值的属性(r属性)是SVG circle元素的属性。由于SVG元素是XML元素,因此SVG属性是XML属性。
你也可以为形状的CSS属性设置动画,如果想这么做,你需要将attributeType设置为CSS。如果你未提供attributeType属性,那么浏览器将尝试猜测添加动画的属性是XML属性还是CSS属性。
animate
animate元素用来为SVG形状的属性添加动画。你可以将animate元素嵌套在形状内。示例如下:
<circle cx="30" cy="30" r="25" style="stroke: none; fill: #0000ff;">
<animate attributeName="cx" attributeType="XML"
from="30" to="470"
begin="0s" dur="5s"
fill="remove" repeatCount="indefinite"/>
</circle><circle cx="30" cy="30" r="25" style="stroke: none; fill: #0000ff;">
<animate attributeName="cx" attributeType="XML"
from="30" to="470"
begin="0s" dur="5s"
fill="remove" repeatCount="indefinite"/>
</circle>这个例子中,将<circle>元素的cx属性从30(from属性)变到了470(to属性)。动画从0秒(begin属性)开始,持续5秒(dur属性)。
当动画结束时,动画属性被设置为原始值(fill="remove"设置)。如果你希望动画结束时动画属性保持最终的值不变,可以将fill属性设置为freeze。动画无限重复(repeatCount属性)。
最终的动画如下:
animateTransform
<animateTransform>元素可以为形状的transform属性设置动画,而<animate>元素不能这么做。
示例如下:
<rect x="20" y="20" width="100" height="40"
style="stroke: #ff00ff; fill:none;" >
<animateTransform attributeName="transform"
type="rotate"
from="0 100 100" to="360 100 100"
begin="0s" dur="10s"
repeatCount="indefinite"
/>
</rect><rect x="20" y="20" width="100" height="40"
style="stroke: #ff00ff; fill:none;" >
<animateTransform attributeName="transform"
type="rotate"
from="0 100 100" to="360 100 100"
begin="0s" dur="10s"
repeatCount="indefinite"
/>
</rect><animateTransform>例子为其外部<rect>元素的transform属性添加动画。其type属性被设置为rotate(旋转变换函数),表示动画变换将是一个旋转。from和to属性被设置为动画需要的参数并传递给rotate函数。该示例围绕点100,100从0度旋转到360度。
下面是一个为正方形添加放大动画的示例:
<rect x="20" y="20" width="40" height="40"
style="stroke: #ff00ff; fill: none;" >
<animateTransform attributeName="transform"
type="scale"
from="1 1" to="2 3"
begin="0s" dur="10s"
repeatCount="indefinite"
/>
</rect><rect x="20" y="20" width="40" height="40"
style="stroke: #ff00ff; fill: none;" >
<animateTransform attributeName="transform"
type="scale"
from="1 1" to="2 3"
begin="0s" dur="10s"
repeatCount="indefinite"
/>
</rect>再次注意,from和to属性包含的值作为参数传递给scale()变换函数。
最终的动画如下:
animateMotion
<animateMotion>元素可以使形状沿着路径的线路移动。它也可以旋转形状以匹配路径的坡度,就像一辆上下行驶的汽车。示例代码如下:
<rect x="0" y="0" width="30" height="15"
style="stroke: #ff0000; fill: none;">
<animateMotion
path="M10,50 q60,50 100,0 q60,-50 100,0"
begin="0s" dur="10s" repeatCount="indefinite"
/>
</rect><rect x="0" y="0" width="30" height="15"
style="stroke: #ff0000; fill: none;">
<animateMotion
path="M10,50 q60,50 100,0 q60,-50 100,0"
begin="0s" dur="10s" repeatCount="indefinite"
/>
</rect>在<animateMotion>元素的path属性中指定用于对矩形进行动画处理的路径。path属性和path元素使用相同的语法。
下面动画中的路径是为了更好的显示运动路径。
为了旋转正方形以与路径的斜率对齐,请将<animateMotion>元素的rotate属性设置为auto。示例如下:
<rect x="0" y="0" width="30" height="15"
style="stroke: #ff0000; fill: none;">
<animateMotion
path="M10,50 q60,50 100,0 q60,-50 100,0"
begin="0s" dur="10s" repeatCount="indefinite"
rotate="auto"
/>
</rect><rect x="0" y="0" width="30" height="15"
style="stroke: #ff0000; fill: none;">
<animateMotion
path="M10,50 q60,50 100,0 q60,-50 100,0"
begin="0s" dur="10s" repeatCount="indefinite"
rotate="auto"
/>
</rect>最终动画如下,注意方向的旋转如何改变以适应路径。
你也可以将rotate属性设置为特定的值,例如20或30等。这将保持形状旋转动画中的度数。
时间单位
当你定义一个SVG动画时,需要指定动画的开始和持续时间。你可以选择不同的时间单位指定它们的值。时间单位通常在各种动画元素的begin,dur和end属性内指定。
在这些属性中,你可以指定一个数字后面带一个时间单位,如本文示例中所做。例如5s表示5秒。下面是一个你可以使用的时间单位的列表:
| 时间单位 | 描述 |
|---|---|
| h | 小时 |
| min | 分钟 |
| s | 秒 |
| ms | 毫秒 |
你也可以包含小时、分钟和秒的时间格式指定时间。格式如下:
hh:mm:sshh:mm:ss示例如下:
1:30:451:30:45此示例指定一个小时,30分钟和45秒的时间(当然,对于动画来说这是非常长的)。
协调动画
你可以同步一个动画的开头到另一个动画的结尾,像下面这样做:
<rect x="0" y="0" width="30" height="15"
style="stroke: #ff0000; fill: none;">
<animate id="one"
attributeName="x" attributeType="XML"
from="0" to="400"
begin="0s" dur="10s" fill="freeze"
/>
<animate
attributeName="y" attributeType="XML"
from="0" to="50"
begin="one.end" dur="10s" fill="freeze"
/>
</rect><rect x="0" y="0" width="30" height="15"
style="stroke: #ff0000; fill: none;">
<animate id="one"
attributeName="x" attributeType="XML"
from="0" to="400"
begin="0s" dur="10s" fill="freeze"
/>
<animate
attributeName="y" attributeType="XML"
from="0" to="50"
begin="one.end" dur="10s" fill="freeze"
/>
</rect>最终动画如下:
第一个动画的id属性为one。
第二个动画引用通过其begin属性引用第一个动画。begin属性值设置为one.end,这意味着当id为one的动画结束时,该动画开始。
你可以使用id.begin或id.end在另一个动画开始或结束时启动动画。使用要同步的动画元素的ID属性替代这里的id。
你也可以像下面这样,为另一个动画的开始和结束时间指定偏移:
one.begin+10s
one.end+5sone.begin+10s
one.end+5s此外,你可以在动画的end属性中显示指定结束时间,这不会替换dur属性。所以无论先发生什么,它所做的就是为动画添加另一个可能的结束。示例如下:
<animate
attributeName="y" attributeType="XML"
from="0" to="50"
begin="one.begin+3s" dur="10s" end="one.end"
fill="freeze"
/><animate
attributeName="y" attributeType="XML"
from="0" to="50"
begin="one.begin+3s" dur="10s" end="one.end"
fill="freeze"
/>这个动画的持续时间为10秒,或者当ID为one的动画结束时停止(以先发生的动画为准)。
重复动画
动画元素上有两个属性可以用来实现重复效果的动画。
第一个属性是repeatCount,你可以为其设置一个数值,动画会重复固定数值的次数,如果将其设置为indefinite,动画会一直保持。
第二个属性是repeatDur,其指定动画重复的持续事件。你也可以将其设置为indefinite,其效果和repeatCount一样。
请看下面两个例子:
<animate
attributeName="y" attributeType="XML"
from="0" to="50"
begin="one.begin+3s" dur="10s"
repeatCount="3"
fill="freeze"
/><animate
attributeName="y" attributeType="XML"
from="0" to="50"
begin="one.begin+3s" dur="10s"
repeatCount="3"
fill="freeze"
/><animate
attributeName="y" attributeType="XML"
from="0" to="50"
begin="one.begin+3s" dur="10s"
repeatDur="30s"
fill="freeze"
/><animate
attributeName="y" attributeType="XML"
from="0" to="50"
begin="one.begin+3s" dur="10s"
repeatDur="30s"
fill="freeze"
/>组合动画
你可以通过在元素中添加多个<animate>来组合动画。你之前已经看到过,但这里是另一个例子:
<rect x="10" y="10" width="40" height="20"
style="stroke: #000000; fill: none;">
<animate attributeName="x"
attributeType="XML"
from="10" to="400"
begin="0s" dur="10s"
repeatCount="indefinite"
/>
<animate attributeName="y"
attributeType="XML"
from="10" to="100"
begin="0s" dur="10s"
fill="freeze"
repeatCount="indefinite"
/>
</rect><rect x="10" y="10" width="40" height="20"
style="stroke: #000000; fill: none;">
<animate attributeName="x"
attributeType="XML"
from="10" to="400"
begin="0s" dur="10s"
repeatCount="indefinite"
/>
<animate attributeName="y"
attributeType="XML"
from="10" to="100"
begin="0s" dur="10s"
fill="freeze"
repeatCount="indefinite"
/>
</rect>这个例子有两个动画,分别为长方形的x和y属性添加动画。最终动画如下:
当组合<animateTransform>元素时,默认行为是第二个动画取消第一个动画。但是,你可以通过向两个<animateTransform>元素添加值为sum的additive属性实现转换动画的组合。示例如下:
<rect x="10" y="10" width="40" height="20"
style="stroke: #000000; fill: none;">
<animateTransform attributeName="transform" attributeType="XML"
type="scale"
from="1" to="3"
begin="0s" dur="10s"
repeatCount="indefinite"
additive="sum"
/>
<animateTransform attributeName="transform" attributeType="XML"
type="rotate"
from="0 30 20" to="360 30 20"
begin="0s" dur="10s"
fill="freeze"
repeatCount="indefinite"
additive="sum"
/><rect x="10" y="10" width="40" height="20"
style="stroke: #000000; fill: none;">
<animateTransform attributeName="transform" attributeType="XML"
type="scale"
from="1" to="3"
begin="0s" dur="10s"
repeatCount="indefinite"
additive="sum"
/>
<animateTransform attributeName="transform" attributeType="XML"
type="rotate"
from="0 30 20" to="360 30 20"
begin="0s" dur="10s"
fill="freeze"
repeatCount="indefinite"
additive="sum"
/>最终动画如下,同时缩放和旋转矩形: