使用 translate、scale、rotate 和 skew 变换 SVG

SVG transformations 会改变图形元素的显示方式,而不重写元素本身的几何属性。使用 transform 属性,可以通过 translate()scale()rotate()skewX()skewY() 移动、调整大小、旋转或倾斜 SVG 形状。同一思想的矩阵形式,请参见 Transformation Matrix

本文将学习:

  • 使用 translate() 移动 SVG 元素。
  • 使用 scale() 调整 SVG 元素大小。
  • 围绕原点或指定点旋转 SVG 元素。
  • 使用 skewX()skewY() 倾斜 SVG 图形。
  • 理解串联多个 transform functions 时顺序为什么重要。

如何变换 SVG 元素

  1. 选择需要变换的 SVG 元素或 group。
  2. 在该元素或父 <g> group 上添加 transform 属性。
  3. 使用 translate(tx, ty) 移动元素。
  4. 使用 scale(sx, sy)rotate(angle cx cy)skewX(angle)skewY(angle) 改变可见几何。
  5. 只有在需要组合效果时才串联 transform functions,并仔细检查顺序。
  6. 仅当单个矩阵比单独 transform functions 更简单时,使用 matrix(a,b,c,d,e,f)

使用 translate() 进行 SVG 平移

Translation 会让元素的每个点移动相同距离。translate(tx, ty) 函数沿 x 轴移动 tx,沿 y 轴移动 ty。如果省略 ty,默认值为 0

参数说明
tx水平偏移(正值向右,负值向左)
ty垂直偏移(正值向下,负值向上)

属性 transform="translate(tx, ty)" 的作用是按公式改变对象坐标:

x(new) = x(old) + tx

y(new) = y(old) + ty

简单示例:

 1<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
 2    <g fill="none">
 3        <!-- no translation -->
 4        <circle cx="15" cy="15" r="10" stroke="blue" />
 5        <!-- horizontal translation -->
 6        <circle cx="15" cy="15" r="10" stroke="black" transform="translate(22)" />
 7        <circle cx="15" cy="15" r="10" stroke="red" transform="translate(44)" />
 8        <!-- both horizontal and vertical translation -->
 9        <circle cx="15" cy="15" r="10" stroke="green" transform="translate(33,13)" />
10        <circle cx="15" cy="15" r="10" stroke="yellow" transform="translate(11,13)" />
11    </g>
12</svg>

代码示例中,<g> 元素把圆组合起来,fill="none" 应用于 group 内的每个圆。下图显示原始圆和被平移的副本( translation.svg):

五环示例,展示 translation transform

使用 scale() 进行 SVG 缩放

Scaling 会按缩放因子放大或缩小元素。scale(sx, sy) 函数把元素宽度乘以 sx,高度乘以 sy。如果省略 sy,SVG 使用与 sx 相同的值,因此元素会等比缩放。

参数说明
sx水平方向缩放因子
sy垂直方向缩放因子,可选
 1<svg viewBox="-50 -50 200 200" xmlns="http://www.w3.org/2000/svg">
 2    <!-- uniform scale -->
 3    <circle cx="0" cy="0" r="10" fill="#B0C4DE" transform="scale(4)" />
 4    <circle cx="0" cy="0" r="10" fill="#DDA0DD" transform="scale(3)" />
 5    <circle cx="0" cy="0" r="10" fill="#FFB6C1" transform="scale(2)" />
 6    <!-- no scale -->
 7    <circle cx="0" cy="0" r="10" fill="#5F9EA0" />
 8    <g transform="translate(100)">
 9        <!-- uniform scale -->
10        <circle cx="0" cy="0" r="10" fill="#B0C4DE" transform="scale(4)" />
11        <!-- vertical scale -->
12        <circle cx="0" cy="0" r="10" fill="#DDA0DD" transform="scale(1,4)" />
13        <!-- horizontal scale -->
14        <circle cx="0" cy="0" r="10" fill="#FFB6C1" transform="scale(4,1)" />
15        <!-- no scale -->
16        <circle cx="0" cy="0" r="10" fill="#5F9EA0" />
17    </g>
18</svg>

渲染结果如下( scaling.svg):

四个彩色圆形展示 scaling

上面的代码使用 scale()translate()。第一组展示等比缩放,两个轴使用相同因子。第二组展示方向性缩放:scale(1,4) 纵向拉伸圆,scale(4,1) 横向拉伸圆。

使用 rotate() 进行 SVG 旋转

rotate(angle, cx, cy) 函数围绕点 (cx, cy) 旋转元素 angle 度。如果省略 cxcy,SVG 会围绕当前坐标系统中的 (0, 0) 旋转元素。

参数说明
angle旋转角度,单位为度(正值顺时针)
cx旋转中心的 x 坐标,可选
cy旋转中心的 y 坐标,可选

所有 rotate 或 skew 角度值都应使用度,不能使用 CSS 中可用的其他角度单位。正角度表示顺时针旋转,负角度表示逆时针旋转。

注意: rotate(angle cx) 是无效的。如果提供旋转中心,必须同时指定 cxcy

与 translation 一样,rotation 不会扭曲元素。它保持距离、角度和平行线不变。

1<svg width="450" height="450" xmlns="http://www.w3.org/2000/svg">
2    <rect x="100" y="250" width="200" height="30" fill="CadetBlue" />
3    <rect x="100" y="250" width="200" height="30" fill="#DDA0DD" transform ="rotate(-45 200 265)" />
4    <rect x="100" y="250" width="200" height="30" fill="Pink" transform ="rotate(-90 200 265)" />
5    <rect x="100" y="250" width="200" height="30" fill="#B0C4DE" transform ="rotate(45 200 265)" />
6    <rect x="100" y="250" width="200" height="30" fill="CadetBlue" transform ="rotate(-35)" />
7</svg>

函数 transform="rotate(-90 200 265)" 会让粉色矩形围绕 (200, 265) 逆时针旋转 90 度。最后一个矩形使用不带中心点的 rotate(-35),因此 SVG 会围绕 (0, 0) 旋转它。结果如下:

五个填充矩形,展示 SVG 围绕点和原点旋转

示例文件 rotation.svg 包含 SVG rotation 示例。

使用 skewX()skewY() 进行 SVG 倾斜

Skewing 通过改变一个坐标轴来倾斜元素。使用 skewX(angle) 沿 x 轴倾斜,使用 skewY(angle) 沿 y 轴倾斜。角度以度为单位。使用 skewX(angle) 时,x 坐标改变而 y 坐标保持不变;使用 skewY(angle) 时,y 坐标改变而 x 坐标保持不变。

下面是使用 skewX(55) 的圆示例( skew-x.svg):

1<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
2    <circle cx="20" cy="20" r="15" stroke="blue" fill="none" />
3    <circle cx="20" cy="20" r="15" stroke="grey" stroke-opacity="0.7" fill="none" transform="skewX(55)" />
4</svg>

下面是使用 skewY(35) 倾斜矩形的简单示例( skew-y.svg):

1<svg  width="800" height="800" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
2   <rect x="20" y="20" width="30" height="30" stroke="blue" stroke-opacity="1" fill="none" />
3   <rect x="20" y="20" width="30" height="30" stroke="grey" stroke-opacity="0.5" fill="none" transform="skewY(35)" />
4 </svg>

渲染示例如下:

应用 skewX 和 skewY 前后的圆和矩形

Common Mistakes and Fixes

问题原因解决方法
应用 translate 后矩形不移动transform 属性拼写错误或缺少引号确认元素上正确设置 transform="translate(150,50)"
Translation 没有应用transform 属性放在父元素而不是目标元素上transform 直接设置到要移动的元素,例如 <rect>
旋转方向与预期相反角度正负号理解错误正值表示顺时针,负值表示逆时针
围绕错误点旋转省略 cx/cy 或设置为元素原点提供明确的旋转中心坐标,或用预平移调整 pivot
Skew 过于夸张角度误用弧度使用,例如 skewX(30)
缩放后元素消失scale factor 被设置为 0 或意外为负使用非零正缩放值;组合变换时验证顺序
组合 transforms 结果错误函数顺序反了记住 transforms 按从右到左应用;写 translate(...) rotate(...) 表示先 rotate 后 translate

Quick Recipes

效果可复制 SVG 代码
向右 50px、向下 30px<rect x="10" y="10" width="40" height="20" transform="translate(50,30)" />
等比放大 2 倍<circle cx="20" cy="20" r="10" transform="scale(2)" />
横向拉伸 3 倍<rect x="0" y="0" width="20" height="20" transform="scale(3,1)" />
围绕中心 (100,100) 旋转 45°<polygon points="90,90 110,90 100,110" transform="rotate(45 100 100)" />
围绕原点顺时针旋转 90°<line x1="0" y1="0" x2="50" y2="0" stroke="black" transform="rotate(90)" />
X 方向倾斜 30°<rect x="10" y="10" width="30" height="30" transform="skewX(30)" />
Y 方向倾斜 -20°<circle cx="25" cy="25" r="15" transform="skewY(-20)" />
组合:移动后旋转<g transform="translate(100,50) rotate(30)"><rect width="40" height="10" fill="red"/></g>

FAQ – SVG Transformations

SVG transform 属性做什么?

transform 属性对 SVG 元素或 group 应用几何变换。它改变元素的显示方式,但不会重写 xycxcy 或 path data 等属性。

translate 和 scale 有什么区别?

translate(tx, ty) 移动元素,不改变尺寸。scale(sx, sy) 改变元素大小,并且可能改变可见位置,因为缩放相对于坐标系统原点执行。

如何围绕中心点旋转 SVG?

使用 rotate(angle cx cy) 并提供两个中心坐标。例如,transform="rotate(45 100 100)" 会围绕点 (100, 100) 旋转 45 度。

什么时候应该使用 matrix 而不是 transform functions?

当可读性重要时,使用 translate()scale()rotate() 等单独函数。当需要一个组合 transform,或来自其他工具/API 的计算值时,使用 matrix(a,b,c,d,e,f)

规范和相关资源