Web编程技术营地
研究、演示、创新

transform 属性

撰写时间:2026-02-19

修订时间:2026-02-22

概述

可通过SVG元素的transform属性来设置其变换。该属性值由CSS Transforms Module Level 1规范。

transform属性值所支持的函数有:

  • 平移:translate(<length-percentage>[,<length-percentage>]?)。参数单位为px
  • 缩放:scale(<number>[,<number>]?)
  • 旋转:rotate([<angle>|<zero>])。只支持一个参数,参数单位为deg。仅调用该函数不能像CSS一样可以通过transform-origin属性来指定旋转中心。
  • 沿X 轴扭曲:skewX([<angle>|<zero>])。
  • 沿Y 轴扭曲:skewY([<angle>|<zero>])。
  • 指定矩阵:matrix(<number>[,<number>]{5,5})。6个参数值分别对应于矩阵的a, b, c, d, e, f

CSS不同的是,SVG元素的transform属性值不支持以下变种函数:

  • translateX()
  • translateY()
  • scaleX()
  • scaleY()
  • skew()

translate()

translate函数将坐标系原点进行平移。

关于SVG 2.0中use元素的样式

为突出平移前与平移后的效果对比,这里使用了use元素来重复引用同一个元素。

使用use元素,将自动产生一个Shadow Tree,并且,所引用元素的CSS样式也将被自动复制到Shadow Tree下面。基于此特点,如果我们直接在rect元素上面设置fillstroke属性值,则这些属性值也将自动复制且不能被覆盖,从而不能产生两种不同的效果。因此,我们不能直接在被引用的rect上面直接设置这些属性值。

解决的方法是,将rect包裹在一个g元素之下,而仅对g元素设置fillstroke属性值。此时,由于rect元素本身无相应属性值,故在Shadow Tree中我们可对use元素设置相应的属性值来表示平移后的效果;而平移前的属性值,由父容器g的属性值自动传递给rect元素。

这样,仅额外使用一个父容器g元素,就可完美解决在引用时需使用两种CSS样式的问题。

translate的平移效果

上面代码,通过将transform的值设置为translate(10, 10),从而进行了平移变换。若省略第二个参数值,则该参数值取零值,如下所示。

scale()

缩放的本质

缩放的本质是,按缩放系数来重新计算SVG元素每个点的位置。

默认情况下,坐标系原点位于(0, 0)的位置,因此,当参数为正数时,矩形从原点向右向下生长;当参数为负数时,矩形从原点向左向上生长;当参数为0时,矩形将坍缩为一个点。

开始时,矩形左上角的坐标为(70, 70),按0.5倍的系数来缩放,则左上角的坐标变为(35, 35),且其宽高值也缩小为一半。可见,基于坐标轴原点的缩放不仅会改变元素的尺寸大小,还会同时改变元素的起始位置,效果不太直观。

现在,我们准备在元素的中心位置上缩放,这样,缩放后元素的大小及位置均可容易地预先判断,并且缩放后,元素不会跑偏。

很显然,我们同时需要平移及缩放两种变换效果,但问题是,是先平移再缩放,还是先缩放再平移?下面分别考查。

先平移再缩放

第一种方式,将缩放前及缩放后的两个元素都置于一个统一的父容器之下,然后对该父容器统一进行平移,以模拟坐标系原点平移的效果。

这种方式,是先在内部进行缩放,然后再由父容器统一进行平移,因此,缩放前后的两个元素的相对位置与上一节的相对位置完全一样,只是缩放完毕后,两个元素再因父容器的原因,整体向右向下平移了10px

第二种方式,先平移缩放前的元素,然后再缩放。

可以看出,这种方式下,计算缩放时只取值于缩放前元素的自身数据,效果是,缩放后,源元素再向右向下平移了40px

先缩放再平移

第一步,先求出缩放前后两个元素的中心坐标值。

第二步,根据两个元素的中心坐标值计算出偏移值,再对缩放后的元素平移该偏移值。

出问题了:缩放后的元素没有移至缩放前元素的中心点的位置。

问题在于,缩放后的偏移值将受缩放因子的影响而变小。解决方法是,在直接计算出两个中心点偏移值后,需将它们再除以缩放因子。修正如下:

由此,我们得出在元素中心缩放时如何计算偏移值的公式如下:

下面将核心功能提炼为一个名为scaleCenter的函数,传入要引用元素的id以及缩放因子,函数将自动生成缩放后的元素:

随意修改要缩放的元素的位置及大小,修改缩放因子,然后再运行,所自动生成的元素的中心位置应能与原来的元素的中心位置始终对齐。

切换到局部坐标系居中缩放

还有另外一种方法,无需复杂的数学计算,只需按照平移、缩放、反向平移的流程编写代码即可。

其原理需要了解更多的技术细节,具体详见下节。

rotate()

基本用法

rotate函数围绕坐标系原点进行旋转。正数顺时针,负数逆时针。

围绕元素中心旋转

要围绕元素中心旋转,可先将坐标系原点平移至元素中心,再旋转,最后以相反的方向再平移回来。

看似简单,但其内部涉及较多细节,下面以动画分步显示:

本例中,为显示坐标系,我们将代表坐标系X轴Y轴的两条直线及需要变换的use元素置于一个g元素之下,然后统一对该g元素进行相应的变换。由于use元素与g之间未作其他的变换操作,因此直接在g元素之上所进行的变换,可视同于直接在use元素之上所进行的变换。

第一步,先将坐标系原点向右向下各平移70px至灰色元素的中心位置。

当我们在某个元素上为其transform属性设置translate()函数时,我们可能一开始就认为,我们改变的是它的xy属性值所代表的实际位置。但实际上不是,它的xy属性值并未改变。正如上面代码效果所示,我们改变的是它的坐标系原点的位置,而它相对于坐标系原点的距离并未发生变化。或者说,我们改变了该元素的局部坐标系中的原点的位置。最终实际位置等于其xy属性值分别加上对应的偏移值。

transform变换的实质是,translate改变局部坐标系的原点,而scalerotate函数则相对于局部坐标系的原点进行变换。更多细节是,使用一个矩阵来存储上述这些函数变换后的状态,而元素每个点的最终位置均系该矩阵与其xy属性值相乘的结果。这些内容,下面章节有详述。因此,元素的局部坐标系也可称为矩阵坐标系

明白了这些细节,对于这一步,更确切的说法是,将元素的局部坐标系原点向右向下各平移70px至全局坐标系中灰色元素的中心位置。

第二步,元素的局部坐标系围绕其原点顺时针旋转45o

注意,在这一步中,元素的整个局部坐标系都进行了旋转,而不是仅元素旋转而坐标系不旋转。

此步的最终结果是,局部坐标系的原点位置不变,但局部坐标系的朝向改变了。

第三步,局部坐标系的原点向左向上各平移70px的位移。

从视觉上看,明明是元素垂直向上平移了,但为何说是元素向左向上平移了?

当我们说,局部坐标系的原点向左向上各平移70px的位移,数学公式为:

即,在X轴上,向原点左边偏移70px取其X轴的坐标值;在Y轴上,向原点上边偏移70px取其Y轴的坐标值。而由于局部坐标系的X轴Y轴均发生了旋转,故在局部坐标系(-70, -70)的点正好落在未发生旋转的全局坐标系的上方。我们产生变换后的元素向上平移的视觉效果,实际上是我们的直觉取变换前的灰色矩形作为参照物,将变换后的青色矩形重新归置于未变换的坐标系与其相比较的结果。

可以说,直觉欺骗了我们,但数学不会。

这就是上一例子中的一行代码:

就能在元素的中心旋转45o的所有内在原因。明白这些内部细节,我们就能精准应对总是不断变化的甲方要求。

skew

可用skewXskewY函数来让元素在相应轴向上扭曲。

skewX()

skewX函数在X轴上产生扭曲,参数中的角度是未产生扭曲的轴向顺时针转向所产生扭曲的轴向之间的夹角。

除产生轴向上的扭曲之外,变换后的元素还向右偏移了特定的数值。原理同上节:这是因为在元素的局部坐标系的原点产生的扭曲的结果。

同样,平移、扭曲、再反向平移,可在元素的中心位置进行定点扭曲。

skewY()

skewY函数在Y轴上产生扭曲,参数中的角度是未产生扭曲的轴向顺时针转向所产生扭曲的轴向之间的夹角。

matrix()

matrix函数共有6个参数,分别对应于该4阶矩阵中具有别名的6个相应元素的数值。这些元素的别名分别为a, b, c, d, e, f

但现在还不是具体讨论矩阵的时候,在这里,我们应专注于如何设置matrix函数的上述6个参数值。

这里将通过反推法,通过上面几节所介绍的方式,先以translate, scale等函数的形式随便设置其变换,然后读取该矩阵的数值,用以构建matrix函数的字符串。

最后一行即是matrix函数的字符串形式,复制它,将其粘帖为下面代码的transform属性值:

两处代码的运行效果完全一样,也即这里的matrix等价于上面的translatescale两个函数的组合。这里可看出,变换矩阵是变换的核心驱动数据。上面各节所谈到的各个函数,均用以设置变换矩阵,最后再根据变换矩阵的数据予以渲染。

参考资源

  1. SVG2: The 'transform' property
  2. CSS Transforms Module Level 1
  3. SVG transform functions
  4. The 'use' element
  5. AnimateTransformElement