好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

SVG进阶 | SVG动画-SMIL(一)

SVG 图形可以使用 动画元素 来制作动画效果。这些动画元素最初被定义在W3C的 SMIL (Synchronized Multimedia Integration Language-同步多媒体集成语言)动画规范中。这些元素包括:

<animate> :它允许你在指定的时间内动画标量的属性。

<set> :在指定的时间之后执行指定的动画。它对于非常数字的属性动画非常有用。

<animateMotion> :沿指定的路径移动元素。

<animateColor> :在指定的时间内修改元素的颜色。这是一个过时的元素,虽然在SVG1.1规范中仍在使用,但是到SVG2.0规范会被移除。

除了在SMIL规范定义的动画元素,SVG还包括了与SMIL动画规范兼容的扩展动画元素。这些扩展包括 <animateMotion> 元素的功能扩展和额外的动画元素。

<animateTransform> :允许你在指定时间内对某个SVG transformation 属性执行动画,例如 transform 属性。

path :这是属性,不是 <path> 元素。

<mpath> :可以和 animateMotion 元素结合来引用一条路径作为运动路径。mpath元素包含在 animateMotion 元素中。

keypoints :属性。作为 animateMotion 元素的一个属性来控制路径动画的动画速度。

rotate :属性。作为 animateMotion 元素的一个属性用于控制路径动画中元素是否自动根据其X轴切线方向来改变运动方向。

浏览器支持

浏览器对SMIL动画的支持非常的好,它可以在除了IE浏览器和Opera Mini浏览器之外的所有现代浏览器中工作。完整的支持列表可以查看 Can I Use 。

如果你需要为SMIL动画提供一个回退方法,你可以使用 Modernizr 。如果浏览器不支持SMIL,你可以为它们提供一些回退方法。

通过 xlink:href 指定动画目标

不论使用4个动画元素中的哪一个,你都需要为它指定一个动画目标。可以使用 xlink:href 属性来指定动画目标。这个属性指向将要执行动画的元素。 这个元素必须在当前的SVG文档中 。

<rect id="cool_shape" ... />
<animate xlink:href="#cool_shape" ... />

动画元素也可以嵌套在SVG元素中。如果没有为动画元素指定 xlink:href 属性,那么动画的目标元素就是当前动画元素的直接父元素。

<rect id="cool_shape" ... >
  <animate ... />
</rect>

因此,你可以将动画元素嵌入到SVG元素中,也可以单独写动画元素,然后使用 xlink:href 属性指向要指向动画的SVG元素。

指定动画的属性

所有的动画元素都有 attributeName 属性,这个属性用于指定当前要指向动画的属性的名称。例如你想在水平方向上移动一个 <circle> 元素的位置,你可以指定 attributeName 属性为 cx 。 attributeName 只有一个值,因此,你每次只能执行一个属性动画。如果你想执行多个属性动画,需要为元素指定多个动画。

你还可以使用 attributeType 属性来为属性指定名称空间。例如可以设置为“CSS”,意思是这些属性可以在CSS中找到。

如果 attributeType 属性没有被明确指定货被设置为 auto ,浏览器会首先查找CSS属性列表中是否有匹配的值,如果没有找到,会去XML名称空间中去查找。

例如下面的例子,在一个SVG矩形上执行 opacity 属性动画,因为 opacity 属性也是一个CSS属性, attributeType 属性可以设置为CSS名称空间。

<rect>
  <animate attributeType="CSS" attributeName="opacity" 
           from="1" to="0" dur="5s" repeatCount="indefinite" />
</rect>
在指定时间内执行元素属性动画

我们从一个简单的位移动画开始,将一个圆形从一个位置移动到另一个位置。我们可以通过改变圆形的 cx 属性来实现这个动画。

制作这个动画效果需要使用 <animate> 元素。它用于在某个时间内动画某个元素的属性。通常属性值为数字或颜色的时候,我们都用 <animate> 来制作动画。至于有哪些属性可以被执行动画,可以查看 W3C的文档 。

为了在指定时间内将一个值修改为另一个值,我们要使用 from , to 和 dur 属性。另外,你还可以使用 begin 属性来指定动画从何时开始。看下面的代码:

<circle id="my-circle" r="30" cx="50" cy="50" fill="orange" />

<animate 
  xlink:href="#my-circle"
  attributeName="cx"
  from="50"
  to="450" 
  dur="1s"
  begin="click"
  fill="freeze" />

在上面的代码中,我们定义了一个橙色的圆形,然后在这个圆形上执行一个动画。圆形的X轴方向的中心从最初的50个单位移动到450个单位。

begin 属性设置为 click ,意思是圆形在被鼠标点击时才开始动画。你也可以将这个值设置为一个时间值,例如: begin="0s" ,那么圆形会在页面一加载完成就开始动画。如果想为动画添加一些延迟效果,可以将这个值设置为正数值。例如: begin="2s" ,那么动画会在页面加载之后2秒才开始执行。

我们甚至还可以将 begin 的值定义为 click + 1s 的形式,这是,动画会 在圆形被鼠标点击1秒之后才开始执行 。

dur 属性相当于CSS中的 animation-duration 。

from 和 to 属性也和CSS帧动画 @keyframe 块中的 from 和 to 相同。

@keyframes moveCircle {
  from { /* 开始值 */ }
  to { /* 结束值 */ }
}

fill 属性(这里要弄清楚它和元素填充属性中的 fill 属性是不同的)和CSS中的 animation-fill-mode 属性类似,用于指定元素在动画结束之后是否返回它的初始状态。它有两个取值:

freeze :动画效果被冻结在最后一个值。

remove :动画效果会在活动周期结束之后被移除。

上面的代码的返回结果如下,用鼠标点击圆形看看效果:

通过 restart 属性重置动画

restart 属性可以防止动画在激活之后被重新开始执行。它有3个可选值:

always :动画可以在任何时候被重置。这是默认值。

whenNotActive :只有在动画没有被激活的时候才能被重置。例如在动画结束之后。

never :在整个SVG执行的过程中,元素动画不能被重置。

同步动画

加入你需要修改一个圆形的坐标和它的颜色,并且颜色的改变发生在圆形移动结束的时候,可以设置颜色改变动画的 begin 属性的值等于它移动的 dur 值。在CSS动画中我们一般也是这样做的。

在SMIL中,提供了一种非常好的事件处理特性。在前面我们就已经说过, begin 属性的取值可以类似 click + 5s 的形式。这个值可以称为“事件值”。在这个例子中它是由一个事件和一个“时钟值( clock value )”组成。为什么是时钟值而不是简单的时间值呢?因为在W3C的文档中,它的取值可以类似“10min”或“1:30”(等于1个小时30分钟),甚至是“03:30:20”(3个小时30分钟20秒)。注意,并不是所有的浏览器都支持这个“时钟值”的。

事件值可以接收的另一种值是另一个动画的ID。如果你有两个动画,你想同步它们,在一个动画之后再执行另一个动画,你可以使用这种方法,最大的好处是不需要知道动画的持续时间。

来看下面的例子,一个蓝色的矩形在圆形开始移动后1秒钟才开始移动。这里通过分别给它们设置一个ID号,然后在 begin 事件中使用这个ID号,代如如下:

<circle id="orange-circle" r="30" cx="50" cy="50" fill="orange" />

<rect id="blue-rectangle" width="50" height="50" x="25" y="200" fill="#0099cc"></rect>

  <animate 
    xlink:href="#orange-circle"
    attributeName="cx"
    from="50"
    to="450" 
    dur="5s"
    begin="click"
    fill="freeze" 
    id="circ-anim" />

  <animate 
    xlink:href="#blue-rectangle"
    attributeName="x" 
    from="50"
    to="425" 
    dur="5s"
    begin="circ-anim.begin + 1s"
    fill="freeze" 
    id="rect-anim" />

begin="circ-anim.begin + 1s" 意思是告诉浏览器矩形在圆形开始运动1秒钟后才开始运动。下面是上面代码的返回结果:

点击上面的圆形开始执行动画,矩形会在圆形运动后1秒钟才开始运动。

你还可以使用 end 事件来设置矩形在圆形结束动画之后才开始运动。

<animate 
    xlink:href="#blue-rectangle"
    attributeName="x" 
    from="50"
    to="425" 
    dur="5s"
    begin="circ-anim.end"
    fill="freeze" 
    id="rect-anim"/>

你甚至还可以更进一步指定矩形在圆形动画结束前多少时间才开始运动。

<animate 
    xlink:href="#blue-rectangle"
    attributeName="x" 
    from="50"
    to="425" 
    dur="5s"
    begin="circ-anim.end - 3s"
    fill="freeze" 
    id="rect-anim"/>
使用 repeatCount 来重复动画次数

如果你想多次执行一个动画,可以使用 repeatCount 属性。你可以指定你想要重复动画的次数,或者使用 indefinite 关键字来指定无限动画。例如我们需要重复圆形的移动动画2次,代码如下:

<animate 
    xlink:href="#orange-circle"
    attributeName="cx"
    from="50"
    to="450" 
    dur="5s"
    begin="click"
    repeatCount="2"
    fill="freeze" 
    id="circ-anim" />

下面是返回结果,另外添加了一个无限运动的矩形。

通过 repeatDur 来限制重复动画的时间

在将一个动画设置为无限循环的动画之后,我们可以使用 repeatDur 属性来限制重复动画的时间。这个时间从从文档被创建开始计算,在到达指定的时间之后,动画将停止。

例如,下面的例子指定圆形在文档被创建之后1分30秒之后停止动画。

<animate 
    xlink:href="#orange-circle"
    attributeName="cx"
    from="50"
    to="450" 
    dur="2s"
    begin="0s"
    repeatCount="indefinite"
    repeatDur="01:30" 
    fill="freeze" 
    id="circ-anim" />
基于动画次数来同步动画

在SMIL中,你可以基于一个动画的重复次数来同步另一个动画。例如,你可以在一个动画重复N此之后开始另一个动画。

下面的例子在圆形重复动画2次之后开始执行无限循环动画。

<animate 
    xlink:href="#blue-rectangle"
    attributeName="x" 
    from="50"
    to="425" 
    dur="5s"
    begin="circ-anim.repeat(2)"
    fill="freeze" 
    id="rect-anim" />
  阅读:72次