33.SVG变换

可以为SVG图像中的形状添加变换。例如移动、缩放和旋转形状。这是显示垂直或对角线文本的一种方便的方法。

变换示例

这里是一个简单的例子:

<svg xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">

    <rect x="50" y="50" height="110" width="110"
          style="stroke:#ff0000; fill: #ccccff"
          transform="translate(30) rotate(45 50 50)"
            >
    </rect>
    <text x="70" y="100"
          transform="translate(30) rotate(45 50 50)"
    >Hello World</text>
</svg>

最终图片如下:

Hello World

请注意<rect><text>元素的transform属性。transform属性指定要应用于形状的变换。此例中,应用了移位和旋转。本文后面将作解释。

什么元素可以被转换?

你可以对所有SVG形状作变换。你也可以将变换应用到<g>元素,因此,能够有效地转换一组元素。也可以变换渐变和填充图案。

变换函数

SVG提供了五个变换函数:

  • translate()

  • rotate()

  • scale()

  • skew()

  • matrix()

接下来将对每个函数作详细解释。

实际上,变换函数不会变换SVG形状本身,而是变换该形状的基础坐标系。因此,即使宽度为20的形状被放大两倍显示,逻辑上它的宽度仍然是20。

translate

translate()函数可以移动形状。你可以将xy作为参数传递给translate()函数。示例代码如下:

translate(50, 25)

这个例子将形状沿x轴移动50个单位,沿y轴移动25个单位。

下面例子展示了两个相同的位置和大小的形状,其中有一个包含位移变换:

<rect x="20" y="20" width="50" height="50"
      style="fill: #cc3333"/>

<rect x="20" y="20" width="50" height="50"
      style="fill: #3333cc"
      transform="translate(75,25)" />

最终图片如下:

请注意,与第一个(红色)形状相比,第二个(蓝色)形状沿x轴移动75个单位,沿y轴移动25个单位。

rotate

rotate()函数绕点0,0旋转形状。下面例子显示了一个矩形(轮廓)和旋转15度后的全等矩形(填充):

<rect x="20" y="20" width="40" height="40"
      style="stroke: #3333cc; fill:none;"
        />

<rect x="20" y="20" width="40" height="40"
      style="fill: #3333cc"
      transform="rotate(15)"
        />

最终图片如下:

如果你想使形状绕另一个点(而非0,0点)旋转,可以将点的x和y坐标传递给rotate函数。下面的例子展示了一个非旋转矩形(轮廓)和围绕其自己的中心旋转15度的全等(填充)矩形:

<rect x="20" y="20" width="40" height="40"
      style="stroke: #3333cc; fill:none;"
        />

<rect x="20" y="20" width="40" height="40"
      style="fill: #3333cc"
      transform="rotate(15, 40, 40)"
        />

最终图片如下:

所有旋转变换都是沿顺时针方向旋转0到360之间的一个度数。如果想沿逆时针方向旋转,你可以传递一个负角度给rotate()函数。

scale

scale()函数用来放大和缩小形状。scale()函数缩放形状尺寸及其位置坐标。因此,位于10,10处宽度为20,高度为30的矩形,放大两倍后,其将出现在20,20处,宽度为40,高度为60。

scale()函数也会缩放形状的描边宽度。

下面的例子展示了一个位于10,0处,宽度为20,高度为20的矩形(蓝色)和一个以2为缩放系数的全等矩形(黑色):

<rect x="10" y="10" width="20" height="30"
      style="stroke: #3333cc; fill:none;" />

<rect x="10" y="10" width="20" height="30"
      style="stroke: #000000; fill:none;"
      transform="scale(2)" />

最终图片如下:

注意矩形的位置和大小是如何缩放的。

你也可以传递两个参数给scale()函数来为矩形在x轴和y轴上使用不同的缩放系数。如下所示:

scale(2, 3)

该示例将形状沿x轴缩放2倍,沿y轴缩放3倍,示例如下:

<rect x="10" y="10" width="20" height="30"
      style="stroke: #3333cc; fill:none;" />

<rect x="10" y="10" width="20" height="30"
      style="stroke: #000000; fill:none;"
      transform="scale(2,3)" />

最终图片如下:

请注意,被缩放的矩形(黑色)的描边宽度同样也被缩放,并且在x轴和y轴上缩放不同。

作为镜像函数的缩放

通过沿x轴或y轴缩放-1,你可以将scale()函数用作镜像函数。在这么做之前,你首先必须沿x或y方向移动(translate)形状,否则镜像形状将出现在SVG画布外面。

示例如下:

<path d="M20,20 l20,20 l0,20 l-20,20 Z"
      style="stroke: #3333cc; fill:none;" />

<path d="M20,20 l20,20 l0,20 l-20,20 Z"
      style="stroke: #000000; fill:none;"
      transform="translate(100, 0) scale(-1, 1) " />

最终图像中在x=100处绘制了一条线(因为矩形在x方向上平移100)。

蓝色是原始形状,黑色是平移和缩放之后的形状。

skew

skewX()skewY()函数使x轴和y轴倾斜。实际上,函数根据某个指定的角度偏斜给定的轴。

下面是一些为skewX()指定不同值的矩形:

<rect x="10" y="10" width="20" height="30"
      style="stroke: #3333cc; fill:none;" />

<rect x="50" y="10" width="20" height="30"
      style="stroke: #000000; fill:none;"
      transform="skewX(10)" />
<rect x="100" y="10" width="20" height="30"
      style="stroke: #000000; fill:none;"
      transform="skewX(45)" />
<rect x="150" y="10" width="20" height="30"
      style="stroke: #000000; fill:none;"
      transform="skewX(60)" />

最终图片如下:

如你所见,skewX()函数使垂直线看起来旋转了给定角度。因此,skewY()函数是水平线看起来像被旋转给定角度。这里有几个例子:

<rect x="10" y="10" width="20" height="30"
      style="stroke: #3333cc; fill:none;" />

<rect x="50" y="10" width="20" height="30"
      style="stroke: #000000; fill:none;"
      transform="skewY(60)" />
<rect x="100" y="10" width="20" height="30"
      style="stroke: #000000; fill:none;"
      transform="skewY(45)" />
<rect x="150" y="10" width="20" height="30"
      style="stroke: #000000; fill:none;"
      transform="skewY(10)" />

matrix

也可以将变换表示为矩阵。矩阵如下所示:

a c e
b d f
0 0 1

由于只能指定前6个值,因此只能为矩阵变换函数提供6个值。示例代码如下:

transform="matrix(a,b,c,d,e,f)"

其它变换也可以表示为矩阵。这里有些例子:

Translate

1 0 tx
0 1 ty
0 0  1

matrix(1,0,0,1,tx,ty)
Rotate

cos(a) -sin(a) 0
sin(a)  cos(a) 0
     0       0 1

matrix(cos(a), sin(a), -sin(a), cos(a), 0, 0)

注意:cos(a)sin(a)的值必须在被插入矩阵之前被预先计算。参数a是旋转的角度。

Scale

sx  0  0
 0 sy  0
 0  0  1

matrix(sx, 0, 0, sy, 0, 0)

沿x轴的偏斜变换可以写成:

Skew

1 tan(a) 0
0      1 0
0      0 1

matrix(1,0,tan(a),1,0,0)

tan(a)的值必须在插入到matrix()函数前进行预先计算。

沿y轴的偏斜变换可以写成:

Skew

1      0 0
tan(a) 1 0
0      0 1

matrix(1,tan(a),0,1,0,0)

下面是一个模仿简单的位移函数的SVG矩阵变换示例:

<rect x="20" y="20" width="50" height="50"
      style="fill: #cc3333"/>

<rect x="20" y="20" width="50" height="50"
      style="fill: #3333cc"
      transform="matrix(1,0,0,1,100,20)"
        />

最终图片如下:

请注意,与左侧(红色)矩形相比,右侧(蓝色)矩形被移位。

组合变换

也可以通过在transform属性中放置多个变换函数来实现组合变换。

下面的例子首先对矩形进行移位变换,然后进行旋转变换。该示例展示了应用变换之前的矩形(蓝色),以及变换之后的矩形(黑色)。

<rect x="50" y="10" width="20" height="30"
      style="stroke: #3333cc; fill:none;"
        />
<rect x="50" y="10" width="20" height="30"
      style="stroke: #000000; fill:none;"
      transform="translate(50,0) rotate(30)" />

最终图片如下:

变换的顺序很重要

变换的顺序很重要,在transform属性内指定的变换函数序列是将它们应用到形状上的顺序。

下面的例子演示了对形状先位移后旋转和先旋转后位移之间的区别:

<rect x="50" y="10" width="20" height="30"
      style="stroke: #000000; stroke-width: 2px; fill:none;"
        />
<rect x="50" y="10" width="20" height="30"
      style="stroke: #3333cc; stroke-width: 2px;  fill:none;"
      transform="translate(100,0) rotate(45)" />
<rect x="50" y="10" width="20" height="30"
      style="stroke: #cc3333; stroke-width: 2px;  fill:none;"
      transform="rotate(45) translate(100,0)" />

最终图片如下:

黑色矩形未作变换,蓝色矩形先位移后旋转,红色矩形先旋转后位移。

最后更新于