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

同时设置多种变换

撰写时间:2026-02-23

修订时间:2026-02-27

以字符串方式设置

上面代码依序进行了平移、旋转、缩放的变换。

函数参数之间以逗号,或空白符隔开,函数之间也以逗号,或空白符隔开。

多种变换的先后顺序

当存在多种变换时,变换结果与变换次序相关。变换次序不一样,其结果也不一样。

取旋转与平移为例。下面先旋转30o,再进行平移。

先旋转,则局部坐标系的原点不变,局部坐标系在原点位置顺时针旋转了30o,局部坐标系朝向发生改变。然后,再沿着局部坐标系朝向向右平移50px的位移。

下面先进行平移,然后再旋转30o

先平移,则局部坐标系的原点向右平移,导致旋转中心发生改变。然后再围绕新的旋转中心进行旋转。

在不同场合下,当我们决定到底先平移还是先旋转时,只需记住一点:平移改变局部坐标系原点;旋转围绕局部坐标系原点进行旋转。

由此,当我们需要围绕任意位置旋转时,可先将局部坐标系原点先平移至该点位置,再旋转,然后再反向平移回来。

下面代码围绕矩形的左下角逆时针旋转45o

对于最后一步的animateTransform,需要解决的问题是,应如何平移变换后的局部坐标系的原点,才能让变换后的元素的左下角返回至变换前的元素的左下角的位置?显然,这需要经过精细的数学计算才能确定当前点与终点。但通过使用by属性值,我们只需将变换后的局部坐标系的原点平移其原先平移的偏移值的相反数值就行了,这样可无需计算当前点与终点的确切位置。

SVGTransformList

除了以字符串方式设置SVG元素的transform属性 (attribute) 值以实现变换之外,还可以对象的方式来设置。

在上面代码,rectSVGGraphicsElement的一个实例,每个这样的实例都有一个名为transform属性 (property)。该属性的类型为SVGAnimatedTransformList。该属性的baseVal代表一个SVGTransformList对象。正如其名,该对象是多个变换 (transforms) 的集合,并提供了以下方法以维护集合元素:

  • voidclear()
  • SVGTransforminitialize(SVGTransformnewItem)
  • getterSVGTransformgetItem(unsigned longindex)
  • settervoid(unsigned longindex, SVGTransformnewItem)
  • SVGTransforminsertItemBefore(SVGTransformnewItem, unsigned longindex)
  • SVGTransformreplaceItem(SVGTransformnewItem, unsigned longindex)
  • SVGTransformremoveItem(unsigned longindex)
  • SVGTransformappendItem(SVGTransformnewItem)
  • SVGTransformcreateSVGTransfomFromMatrix(DOMMatrixReadOnlymatrix)
  • SVGTransform? consolidate()

多数方法的参数都需传入一个代表变换的SVGTransform对象。

上面的rect元素尚未设置任何变换,但其transformList照样存在,只不过该对象的length属性值为0

SVGTransform

初窥SVGTransform

上面先以字面符的形式,将rect元素的transform属性值设置为translate(10,35),这样,transformList就含有了一个SVGTransform对象,其type属性值为2,对应于常量SVG_TRANSFORM_TRANSLATE的值,因此该对象代表一个平移的变换。matrix属性值以SVGMatrix的方式存储了其所有变换的内部矩阵数据。

每种表示变换的字面符函数,都会自动生成一个对应的SVGTransform对象。而对于每一个SVGTransform对象,我们均可选择下面其中的一个方法来设置(或改变)其矩阵数据:

  1. voidsetMatrix(DOMMatrixReadOnlymatrix)
  2. voidsetTranslate(floattx, floatty)
  3. voidsetScale(floatsx, floatsy)
  4. voidsetRotate(floatangle, floatcx, floatcy)
  5. voidsetSkewX(floatangle)
  6. voidsetSkewY(floatangle)

直接修改现有的SVGTransform

因此,对于上面已有的的平移变换,我们可以直接将该变换设置为新的变换,如旋转。

上面的rect原来的变换为平移,通过调用setRotate方法,让原有的变换改变为一个旋转的变换。

有几个要点需注意:

  1. 在一个原来的transform上面调用setXXX方法,将直接覆盖原来的变换。尽管原来的变换已平移至(10,35)的位置,但调用setRotate方法后,平移变换被移除,只有旋转一种变换。
  2. 调用setRotate后,transform对象的matrix属性值已被替换为旋转变换的内容,并且,type属性值由原来的SVG_TRANSFORM_TRANSLATE变更为SVG_TRANSFORM_ROTATE
  3. setRotate方法很方便,可围绕第2个参数及第3个参数所表示的坐标值上旋转第1个参数所表示的角度。它在后台自动帮我们完成了上面所谈到的平移、旋转、再反向平移的一系列过程。
  4. setScale方法可没这么方便,它只有2个参数,分别代表X轴Y轴上的缩放量,无法指定在特定位置上进行缩放,因此需组合多个SVGTransform才能达到定点缩放的效果。

一般情况下,我们较少这样直接修改一个已经存在的SVGTransform,而是通过SVGTransformList所提供的APIs来增删集合中的各种变换。

手工创建新的SVGTransform对象

开始时,rect没有设置任何变换。

先调用根元素SVGSVGElementcreateSVGTransform方法,创建一个新的SVGTransform对象,其type类型默认为SVG_TRANSFORM_MATRIX。然后调用变量transformsetTranslate方法设置为平移变换,type类型自动更新为SVG_TRANSFORM_TRANSLATE。最后,调用变量transformListappendItem方法,将其添加到变换集合中。这就完成了插入一个新变换对象的完整过程。

核心代码归结如下:

参考资源

  1. SVG2: The 'transform' property
  2. CSS Transforms Module Level 1
  3. SVG transform functions
  4. The 'use' element
  5. AnimateTransformElement
  6. Web Animations
  7. CSS: local coordinate system
  8. The Animatable interface mixin
  9. Additive Animation with the Web Animations API