SVG 坐标系统和单位 – SVG Viewport 与 viewBox

所有 SVG 内容都绘制在 SVG viewport 内。每个 SVG viewport 都定义一个绘图区,该区域由尺寸(width、height)和以抽象用户单位度量的原点描述。( W3C

canvas 是放置 SVG 元素的无限空间。屏幕或容器限制出来的可见部分称为 viewport。理解 canvas、viewport 和 viewBox 的关系,是精确控制 SVG 布局和响应式缩放的基础。

本文说明

  • canvas 是抽象的 SVG 绘图空间。
  • viewport 是由 widthheight 定义的可见窗口。
  • 初始坐标系统从左上角 (0,0) 开始。
  • SVG 使用用户单位表示坐标和长度。
  • viewBox 可以创建不同的用户坐标系统,用于缩放、放大和定位。

Canvas 与 Viewport

canvas 是一个抽象且无限的平面,可以包含正坐标和负坐标。所有 SVG 内容最终都必须显示在 viewport 中。viewport 是 canvas 上的一个可见区域,由尺寸和原点描述,默认原点为 (0,0)。最外层 <svg> 元素上的 widthheight 属性定义初始 viewport 的范围。

1    <svg width="900" height="500" xmlns="http://www.w3.org/2000/svg">
2    </svg>

上面的代码设置了 SVG viewport 的 widthheight。可以把它理解为通过一个 900×500 像素的“窗口”观看图形。这样的 viewport 称为初始 viewport

canvas 和初始 viewport

初始坐标系统与用户坐标系统

SVG 中对象的位置和尺寸都由坐标描述。默认 SVG 坐标系统与 HTML 中常见的屏幕坐标类似,是一个二维 x-y 平面。原点 (0,0) 位于左上角,正 x 方向向右,正 y 方向向下。坐标、width 和 height 可以使用 cm, mm, in, em, ex, pt, pcpx 等单位;默认 SVG 单位通常是像素。

需要区分初始 SVG 坐标系统和 viewport 的用户 SVG 坐标系统。最外层 <svg> 元素可以包含 viewBox 属性。如果没有 viewBox,用户坐标系统通常与初始坐标系统相同。

viewBox 属性设置一个用户坐标系统,它可以与初始坐标系统不同。viewBox 接受四个值:

属性值应写在引号内:viewBox="min-x min-y width height"

viewport 像一个窗口,通过它观看 SVG 内容。viewBox 也像一个可选择的观察区域,并可用于放大显示。看下面的例子:

1    <svg width="900" height="500" viewBox="220 125 450 250" xmlns="http://www.w3.org/2000/svg">
2    </svg>

这段代码中,viewBox 选择 canvas 上一个矩形区域:原点为 (220,125),宽度为 450,高度为 250。然后 SVG 会把这个区域裁剪出来,并放大到填满整个 viewport。

初始 viewport 和用户 viewBox

左图显示无限 SVG document canvas、初始 SVG viewport 和用户 viewBox;右图显示应用 viewBox 后的渲染结果。

使用 viewBox 后,用户坐标系统中的单位会被映射到 viewport 中。换句话说,viewBox 选中的坐标矩形会被缩放到可见区域里。修改 viewBox 的四个值可以放大、缩小、裁剪或沿坐标轴移动原始图像。除此之外,SVG 坐标系统还可以通过变换进行旋转、倾斜和翻转。

如何读取 SVG 坐标和单位

  1. 从最外层 <svg> 元素开始,检查它的 widthheight
  2. (0,0) 理解为初始 viewport 的左上角。
  3. x 值理解为向右移动,将 y 值理解为向下移动。
  4. 检查是否存在 viewBox,因为它会把用户坐标重新映射到 viewport。
  5. 使用各元素的坐标属性,如 xycxcypoints 或 path commands 来放置内容。

Common Mistakes and Fixes

问题原因修复方法
SVG 内容被裁剪viewBox 定义的区域小于实际绘制内容增大 viewBox 的 widthheight,或调整 min-x / min-y
SVG 看起来被拉伸viewBox 宽高比与 viewport 不一致保持 viewBox 尺寸比例一致,或用 preserveAspectRatio 控制缩放
对象过大或过小误解了用户坐标系统的缩放关系根据 viewport 尺寸重新计算 viewBox 单位
内容位置意外偏移viewBoxmin-xmin-y 不正确调整原点值,使目标内容区域对齐
修改 viewBox 后没有变化定义区域内没有可见内容确认绘制元素位于 viewBox 边界内

Quick Recipes

任务SVG 示例
定义固定 viewport<svg width="400" height="200"></svg>
让 SVG 可缩放<svg width="400" height="200" viewBox="0 0 400 200"></svg>
放大到特定区域<svg width="400" height="200" viewBox="100 50 200 100"></svg>

FAQ – SVG 坐标和单位

SVG viewport 和 viewBox 有什么区别?

viewport 是可见输出区域,通常由 widthheight、CSS 或布局容器定义。viewBox 定义被映射到该 viewport 中的坐标矩形。

为什么 SVG 的 y 轴向下?

初始 SVG 坐标系统从左上角 (0,0) 开始。正 x 值向右,正 y 值向下,这与许多屏幕坐标系统一致。

什么是 SVG 用户单位?

用户单位是在 SVG 绘图内部使用的坐标单位。没有 viewBox 时,一个用户单位通常对应一个 CSS 像素;有 viewBox 时,用户单位会被缩放以适配 viewport。

为什么修改 viewBox 会让 SVG 内容变大或变小?

SVG 会把 viewBox 矩形缩放到填满 viewport。较小的 viewBox 显示更少用户单位,因此内容看起来更大;较大的 viewBox 显示更多用户单位,因此内容看起来更小。

规范和相关资源