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

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

 

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度,我们将会得到下图的效果(图中的小圆点是它们各种的原点)。

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

如果我们想根据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>

得到的结果如下图所示:

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

必须指出的是,到写这篇文章为止,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>

DEMO

注意,到目前为止,在使用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;
}
/* … */

DEMO

如果两条线和间隙的值都相等的话,你也可以使用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同样的事情。

 

出处:http://www.htmleaf.com/ziliaoku/qianduanjiaocheng/201503141522.html

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

下载:201503142148

Leave a Reply