当前位置主页 > 资料库 > 前端教程 > 如何使用CSS来修改SVG原点和制作SVG动画

如何使用CSS来修改SVG原点和制作SVG动画

2015-03-14

查看演示 下载地址

SVG元素可以像HTML元素一样,使用CSS keyframes和animation属性或者CSS transitions来制作各种动画效果。

大多数情况下,一个复杂的动画效果需要组合多种变换效果:旋转、倾斜、缩放以及他们的转换和过渡效果。多数情况下,SVG元素和HTML元素在使用transformtransform-origin上是相同的。但它们之间也有不同之处,SVG元素不能使用box model来管理,因此,它没有marginpaddingborder或content boxes。

默认情况下,一个HTML元素的transform原点位于该元素的(50%, 50%)的地方,这里是元素的中心点。与之不同,SVG元素的transform原点位于当前用户坐标系统的原点上,这个点是画布的左上角位置。

假设我们有一个<div>和一个SVG <rect>元素:

<!DOCTYPE html>
…
<div style="width: 100px; height: 100px; background-color: orange"> </div>
<svg style="width: 150px; height: 150px; background-color: #eee">
  <rect width="100" height="100" x="25" y="25" fill="orange" />
</svg>                              
                            

如果我们在没有改变原点的情况下,都将它们旋转45度,我们将会得到下图的效果(图中的小圆点是它们各种的原点)。

HTML元素和SVG元素按各自的原点分别旋转45度

如果我们想根据SVG元素的自身原点,而不是用户坐标系原点来旋转SVG图形该怎么办呢?我们需要使用transform-origin属性来明确的设置SVG元素的transform原点位置。

在HTML元素上设置转换原点是一件非常简单的事情:你设置的任何值都是相对于元素的border box。

在SVG中,transform原点可以使用百分比值或一个绝度值(如像素)来设置。如果你使用百分比值来设置transform-origin,这个值被设置为相对于元素的bounding box,它包括用于绘制边框的stroke。如果你使用一个绝对值来来设置transform-origin,那么这个值被设置为相对于用户的当前坐标系统,即SVG的画布。

如果我们要将上例中的<div><rect>都使用百分比来设置其transform原点到中心,代码如下:

<!DOCTYPE html>
<style>
  div, rect {
  transform-origin: 50% 50%;
}
</style>                             
                            

得到的结果如下图所示:

HTML元素和SVG元素各自将原点转换到中心点并旋转45度

必须指出的是,到写这篇文章为止,Firefox浏览器仍不支持使用百分比来设置transform的原点,这是一个总所周知的bug。因此,目前最好还是使用绝对值来设置transform的原点。你仍可以在webkit内核的浏览器中使用百分比来设置原点。

下面是一个SVG风车的小例子,我们使用CSS animation来使它不停的旋转。为了使风车绕指定的原点旋转,我们同时使用像素和百分比来设置它的transform原点。

<svg>
<style>
.wheel {
  transform-origin: 193px 164px;
  -webkit-transform-origin: 50% 50%;
  -webkit-animation: rotate 4s cubic-bezier(.49,.05,.32,1.04) infinite alternate;
  animation: rotate 4s cubic-bezier(.49,.05,.32,1.04) infinite alternate;
}
@-webkit-keyframes rotate {
  50% {
    -webkit-transform: rotate(360deg);
  }
}
@keyframes rotate {
  50% {
    transform: rotate(360deg);
  }
}
</style>
<!-- SVG content -->
</svg>                              
                            

查看示例

注意,到目前为止,在使用SVG元素的时候,CSS 3D transformations是没有硬件加速的,只是在SVG transform属性上做了一些优化。但是,Firefox 浏览器对SVG的transforms有一定的加速效果。

SVG路径动画

我们没有办法使用CSS将一个SVG图像转换为另外一个图形。如果你想制作路径变形动画,那么你需要使用javascript。我们建议使用Dmitry Baranovskiy写的Snap.svg

使用Snap.svg可以很容易的处理一写怪异的问题。

你可以使用CSS来创建动态的画线效果,这个效果你需要知道画线路径的总长度,然后使用SVG的stroke-dashoffsetstroke-dasharray属性来制作画线效果,如果你知道画线路径的总长度,可以使用下面的CSS代码来制作这个动画效果:

#path {
stroke-dasharray: pathLength;
stroke-dashoffset: pathLength;
/* transition stroke-dashoffset */
transition: stroke-dashoffset 2s linear;
}

svg:hover #path{
  stroke-dashoffset: 0;
}                              
                            

上面的代码中,当鼠标滑过SVG元素时,路径会向前绘制2秒钟。

在下面的这个例子中,我们使用相同的技术-一个带延迟的CSS transition来制作一个电灯泡通电的效果。

#cable {
  stroke: #FFF2B1;
  stroke-dasharray: 4000 4000;  
  stroke-dashoffset: 4000;
  stroke-width: 4;
  transition: stroke-dashoffset 8s linear;
}

svg:hover #cable {
  stroke-dashoffset: 0;
}

/* turn lamp on */
.inner-lamp{
  fill:grey;
  transition: fill .5s ease-in 6s;
}

svg:hover .inner-lamp {
  fill: #FBFFF8;
}
/* … */                              
                            

查看示例

如果两条线和间隙的值都相等的话,你也可以使用stroke-dasharray: 4000;来替换stroke-dasharray: 4000 4000

有些时候你不知道动画路径的总长度,这时,你可以使用javascript的getTotalLength()方法来获取路径的长度。

var path = document.querySelector('.drawing-path');
path.getTotalLength();
//set CSS properties up
path.style.strokeDasharray = length;
path.style.strokeDashoffset = length;
//set transition up
path.style.transition = 'stroke-dashoffset 2s ease-in-out';
// animate
path.style.strokeDashoffset = '0';                              
                            

上面的代码说明我们可以使用javascript来完成和CSS同样的事情。

查看演示 下载地址

Previous:
上一篇:使用SVG制作圆形菜单以及制作圆形菜单动画特效
Next:
下一篇:CSS的角度、时间和频率测量单位
返回顶部