{T}

变换操作

transform 属性允许你对 SVG 元素进行平移、缩放、旋转和倾斜等变换。这些变换是基于元素自身的坐标系。

变换基础

SVG 的 transform 属性支持以下变换函数:

  • translate(tx, ty) - 平移
  • scale(sx, sy) - 缩放
  • rotate(angle, cx, cy) - 旋转
  • skewX(angle) - X 轴倾斜
  • skewY(angle) - Y 轴倾斜
  • matrix(a, b, c, d, e, f) - 矩阵变换

基本语法

xml
<rect x="10" y="10" width="50" height="50" transform="translate(20, 30)" />

平移 translate

平移变换,将元素沿 x 轴移动 tx,沿 y 轴移动 ty

语法

xml
translate(tx, [ty])
  • tx: x 轴方向的位移
  • ty: y 轴方向的位移(可选,默认为 0)

示例

xml
<svg width="200" height="100">
    <rect x="10" y="10" width="50" height="50" fill="blue" />
    <rect x="10" y="10" width="50" height="50" fill="lightblue" transform="translate(70, 10)" />
</svg>

缩放 scale

缩放变换。如果只提供一个参数 sx,则在 x 和 y 方向上等比缩放。如果提供 sy,则分别在 x 和 y 方向上缩放。缩放的中心点默认为 (0,0)

语法

xml
scale(sx, [sy])
  • sx: x 轴方向的缩放比例
  • sy: y 轴方向的缩放比例(可选,默认等于 sx)

示例

xml
<svg width="200" height="100">
    <rect x="20" y="20" width="50" height="50" fill="green" transform="scale(1.5)" />
</svg>

缩放中心点

默认情况下,缩放以原点 (0, 0) 为中心。如果需要以元素中心为缩放中心,需要结合 translate:

xml
<svg width="200" height="200">
    <!-- 以元素中心为缩放中心 -->
    <rect x="75" y="75" width="50" height="50" fill="red"
          transform="translate(100, 100) scale(1.5) translate(-100, -100)" />
</svg>

旋转 rotate

旋转变换。angle 是旋转角度。可选的 (cx, cy) 是旋转中心点,默认为元素坐标系的原点 (0, 0)

语法

xml
rotate(angle, [cx, cy])
  • angle: 旋转角度(度)
  • cx: 旋转中心的 x 坐标(可选)
  • cy: 旋转中心的 y 坐标(可选)

示例

xml
<svg width="200" height="100">
    <rect x="70" y="20" width="50" height="50" fill="purple" transform="rotate(45, 95, 45)" />
</svg>

以元素中心旋转

xml
<svg width="200" height="200">
    <!-- 以元素中心旋转 45 度 -->
    <rect x="75" y="75" width="50" height="50" fill="orange"
          transform="rotate(45, 100, 100)" />
</svg>

倾斜 skew

倾斜变换,分别沿 x 轴和 y 轴倾斜指定的角度。

skewX

沿 x 轴倾斜:

xml
skewX(angle)

skewY

沿 y 轴倾斜:

xml
skewY(angle)

示例

xml
<svg width="200" height="100">
    <rect x="20" y="20" width="50" height="50" fill="orange" transform="skewX(20)" />
</svg>

矩阵变换 matrix

matrix 是最强大的变换,它使用一个 3x3 的变换矩阵来描述坐标变换。由于 SVG 中的变换是仿射变换,第三列总是 (0, 0, 1),所以只需要提供 6 个参数。

语法

xml
matrix(a, b, c, d, e, f)

变换公式:

code
x' = a*x + c*y + e
y' = b*x + d*y + f

这允许你组合任意的平移、缩放、旋转和倾斜。

示例

xml
<svg width="200" height="100">
    <rect x="10" y="10" width="50" height="50" fill="red" transform="matrix(1, 0.5, -0.5, 1, 30, 10)" />
</svg>

常见变换的矩阵表示

  • 平移: matrix(1, 0, 0, 1, tx, ty)
  • 缩放: matrix(sx, 0, 0, sy, 0, 0)
  • 旋转: matrix(cos(θ), sin(θ), -sin(θ), cos(θ), 0, 0)
  • 倾斜: matrix(1, tan(θy), tan(θx), 1, 0, 0)

组合变换

可以同时应用多个变换,用空格隔开。变换会从右到左依次应用。这意味着最右边的变换最先作用于元素。

语法

xml
transform="transform1 transform2 transform3 ..."

执行顺序

变换按照从右到左的顺序执行:

xml
<!-- 先缩放1.2倍,再旋转30度,最后平移 (100, 0) -->
<rect transform="translate(100, 0) rotate(30) scale(1.2)" />

示例

xml
<svg width="200" height="100">
    <!-- 先缩放1.2倍,再旋转30度,最后平移 (100, 0) -->
    <rect x="10" y="10" width="50" height="50" fill="red" transform="translate(100, 0) rotate(30) scale(1.2)" />
</svg>

变换原点

默认情况下,变换以元素坐标系的原点 (0, 0) 为中心。可以通过以下方式改变变换原点:

方法 1: 使用 transform-origin (CSS)

xml
<svg width="200" height="200">
    <style>
        .center-transform {
            transform-origin: center center;
        }
    </style>
    <rect class="center-transform" x="75" y="75" width="50" height="50" fill="blue" transform="rotate(45)" />
</svg>

方法 2: 使用 translate 组合

xml
<svg width="200" height="200">
    <!-- 以元素中心 (100, 100) 为旋转中心 -->
    <rect x="75" y="75" width="50" height="50" fill="red"
          transform="translate(100, 100) rotate(45) translate(-100, -100)" />
</svg>

方法 3: 使用 rotate 的中心参数

xml
<svg width="200" height="200">
    <!-- 以 (100, 100) 为旋转中心 -->
    <rect x="75" y="75" width="50" height="50" fill="green" transform="rotate(45, 100, 100)" />
</svg>

实际应用示例

旋转时钟

html
<svg width="200" height="200">
    <circle cx="100" cy="100" r="90" fill="none" stroke="black" stroke-width="2"/>
    
    <!-- 时针 -->
    <line x1="100" y1="100" x2="100" y2="50" stroke="black" stroke-width="4"
          transform="rotate(0, 100, 100)">
        <animateTransform
            attributeName="transform"
            type="rotate"
            from="0 100 100"
            to="360 100 100"
            dur="43200s"
            repeatCount="indefinite"/>
    </line>
    
    <!-- 分针 -->
    <line x1="100" y1="100" x2="100" y2="30" stroke="black" stroke-width="2"
          transform="rotate(0, 100, 100)">
        <animateTransform
            attributeName="transform"
            type="rotate"
            from="0 100 100"
            to="360 100 100"
            dur="3600s"
            repeatCount="indefinite"/>
    </line>
</svg>

缩放动画

html
<svg width="200" height="200">
    <rect x="75" y="75" width="50" height="50" fill="blue">
        <animateTransform
            attributeName="transform"
            type="scale"
            values="1;1.5;1"
            dur="2s"
            repeatCount="indefinite"/>
    </rect>
</svg>

组合变换动画

html
<svg width="200" height="200">
    <rect x="75" y="75" width="50" height="50" fill="purple">
        <animateTransform
            attributeName="transform"
            type="translate"
            values="0,0;50,50;0,0"
            dur="3s"
            repeatCount="indefinite"
            additive="sum"/>
        <animateTransform
            attributeName="transform"
            type="rotate"
            values="0 100 100;360 100 100;0 100 100"
            dur="3s"
            repeatCount="indefinite"
            additive="sum"/>
    </rect>
</svg>

常见问题

1. 变换会累积吗?

是的,如果元素有多个 transform 属性或动画,变换会累积。可以使用 additive="replace" 来替换而不是累积。

2. transform 和 CSS transform 有什么区别?

  • SVG 的 transform 是属性,CSS 的 transform 是样式
  • SVG 的 transform 不支持 transform-origin 属性
  • SVG 的 transform 可以使用 SMIL 动画

3. 如何实现以元素中心为变换原点?

使用 translate 组合:

xml
transform="translate(cx, cy) rotate(angle) translate(-cx, -cy)"

参考资源