{T}

坐标与视口

SVG 使用的坐标系统是笛卡尔坐标系,以左上角为原点 (0,0),x 轴向右增长,y 轴向下增长。理解 SVG 的坐标系统对于精确控制图形的位置和尺寸至关重要。

坐标系统基础

SVG 使用笛卡尔坐标系统:

  • 原点: 左上角 (0, 0)
  • X 轴: 向右增长
  • Y 轴: 向下增长
  • 单位: 默认为像素(px),也可以使用其他单位(cm, mm, in, pt, pc 等)

视口(Viewport)

视口是 SVG 的可见区域,由 widthheight 属性定义:

xml
<svg width="200" height="100">
  <!-- 视口尺寸为 200x100 像素 -->
</svg>

用户坐标系

用户坐标系是 SVG 内部使用的坐标系统,可以通过 viewBox 属性定义。


viewBox 属性

viewBox 是 SVG 中至关重要的属性,它定义了 SVG 画布上可见区域的坐标系。viewBox 允许独立于 SVG 的 widthheight 来定义图形的坐标空间。这创建了一个用户坐标系,使得图形可以独立于视口尺寸进行缩放。

语法

xml
viewBox="min-x min-y width height"
  • min-x: 可视区域左上角的 x 坐标
  • min-y: 可视区域左上角的 y 坐标
  • width: 可视区域的宽度
  • height: 可视区域的高度

基本示例

xml
<svg width="200" height="100" viewBox="0 0 400 200" style="border: 1px solid #ccc;">
  <!-- 这个圆形在 400x200 的坐标系中绘制 -->
  <circle cx="200" cy="100" r="80" fill="lightblue"/>
</svg>

示例中:viewBox 定义 400x200 的内部坐标系(用户坐标系),而 SVG 的实际尺寸是 200x100(视口)。浏览器会自动将 400x200viewBox 缩放到 200x100 的视口中,相当于将图形缩小了一半。

缩放效果

通过 viewBox 可以实现图形的缩放:

html
<svg width="200" height="200" viewBox="0 0 100 100">
  <!-- viewBox 比视口小,图形会被放大 -->
  <circle cx="50" cy="50" r="40" fill="blue"/>
</svg>

<svg width="200" height="200" viewBox="0 0 400 400">
  <!-- viewBox 比视口大,图形会被缩小 -->
  <circle cx="200" cy="200" r="160" fill="red"/>
</svg>

平移效果

通过调整 viewBoxmin-xmin-y 可以实现平移:

html
<svg width="200" height="200" viewBox="50 50 100 100">
  <!-- 只显示 viewBox 指定的区域 -->
  <rect x="0" y="0" width="200" height="200" fill="lightblue"/>
</svg>

preserveAspectRatio 属性

preserveAspectRatio 属性用于控制当 viewBox 的宽高比与 SVG 视口的宽高比不匹配时,图形如何缩放和对齐。默认值为 xMidYMid meet

语法

xml
preserveAspectRatio="align meetOrSlice"

对齐方式(align)

描述
xMinYMin左上对齐
xMidYMin水平居中,顶部对齐
xMaxYMin右上对齐
xMinYMid左对齐,垂直居中
xMidYMid水平和垂直居中
xMaxYMid右对齐,垂直居中
xMinYMax左下对齐
xMidYMax水平居中,底部对齐
xMaxYMax右下对齐

缩放方式(meetOrSlice)

描述
meet保持宽高比,缩放以适应视口(默认)
slice保持宽高比,缩放以填充视口,可能裁剪内容
none不保持宽高比,拉伸以填充视口

示例对比

html
<svg width="200" height="100" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet">
  <!-- 居中对齐,保持宽高比 -->
  <rect x="0" y="0" width="100" height="100" fill="blue"/>
</svg>

<svg width="200" height="100" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid slice">
  <!-- 居中对齐,填充视口,可能裁剪 -->
  <rect x="0" y="0" width="100" height="100" fill="red"/>
</svg>

<svg width="200" height="100" viewBox="0 0 100 100" preserveAspectRatio="none">
  <!-- 拉伸以填充视口,不保持宽高比 -->
  <rect x="0" y="0" width="100" height="100" fill="green"/>
</svg>

嵌套 SVG 与坐标系

当一个 <svg> 元素嵌套在另一个 <svg> 元素内部时,会创建一个新的坐标系。内部 <svg>xy 属性定义了它在父坐标系中的位置。

基本示例

xml
<svg width="200" height="200" style="border: 1px solid black;">
  <!-- 外部 SVG -->
  <rect x="10" y="10" width="180" height="180" fill="lightgray" />

  <!-- 嵌套 SVG,创建新的视口和坐标系 -->
  <svg x="50" y="50" width="100" height="100" viewBox="0 0 50 50">
    <!-- 这个圆形是在 50x50 的 viewBox 中绘制的,但会根据 100x100 的视口放大 -->
    <circle cx="25" cy="25" r="25" fill="blue" />
  </svg>
</svg>

应用场景

嵌套 SVG 常用于:

  1. 创建独立的坐标系统: 不同部分使用不同的缩放比例
  2. 实现局部滚动: 在 SVG 内部创建可滚动区域
  3. 性能优化: 将频繁更新的部分隔离到单独的 SVG 中

实际应用示例

响应式 SVG

html
<!DOCTYPE html>
<html>
<head>
  <style>
    .responsive-svg {
      width: 100%;
      height: auto;
    }
  </style>
</head>
<body>
  <!-- 使用 viewBox 实现 SVG 响应式 -->
  <svg class="responsive-svg" viewBox="0 0 100 100">
    <circle cx="50" cy="50" r="40" fill="blue"/>
  </svg>
</body>
</html>

SVG 地图缩放

html
<svg width="600" height="400" viewBox="0 0 1200 800">
  <!-- 大尺寸地图,自动缩放到 600x400 -->
  <rect x="0" y="0" width="1200" height="800" fill="#f0f0f0"/>
  
  <!-- 地图内容 -->
  <circle cx="600" cy="400" r="50" fill="red"/>
  <text x="600" y="410" text-anchor="middle">地图中心</text>
</svg>

SVG 缩略图

html
<div style="display: flex; gap: 20px;">
  <!-- 原始大小 -->
  <svg width="200" height="200" viewBox="0 0 200 200">
    <circle cx="100" cy="100" r="80" fill="blue"/>
  </svg>
  
  <!-- 缩略图 -->
  <svg width="100" height="100" viewBox="0 0 200 200">
    <circle cx="100" cy="100" r="80" fill="blue"/>
  </svg>
  
  <!-- 更小的缩略图 -->
  <svg width="50" height="50" viewBox="0 0 200 200">
    <circle cx="100" cy="100" r="80" fill="blue"/>
  </svg>
</div>

常见问题

1. viewBox 和 width/height 的区别?

  • width/height: 定义 SVG 在页面上的显示尺寸(视口)
  • viewBox: 定义 SVG 内部的坐标系统(用户坐标系)
  • 当 viewBox 和视口宽高比不一致时,可以通过 preserveAspectRatio 控制对齐方式

2. 如何让 SVG 响应式?

设置 width: 100%height: auto,并使用 viewBox:

css
svg {
  width: 100%;
  height: auto;
}

3. viewBox 的坐标可以是负数吗?

可以,负数坐标表示原点左上方的区域:

xml
<svg width="200" height="200" viewBox="-100 -100 200 200">
  <circle cx="0" cy="0" r="50" fill="blue"/>
</svg>

参考资源