坐标与视口
SVG 使用的坐标系统是笛卡尔坐标系,以左上角为原点 (0,0),x 轴向右增长,y 轴向下增长。理解 SVG 的坐标系统对于精确控制图形的位置和尺寸至关重要。
坐标系统基础
SVG 使用笛卡尔坐标系统:
- 原点: 左上角
(0, 0) - X 轴: 向右增长
- Y 轴: 向下增长
- 单位: 默认为像素(px),也可以使用其他单位(cm, mm, in, pt, pc 等)
视口(Viewport)
视口是 SVG 的可见区域,由 width 和 height 属性定义:
xml
<svg width="200" height="100">
<!-- 视口尺寸为 200x100 像素 -->
</svg>用户坐标系
用户坐标系是 SVG 内部使用的坐标系统,可以通过 viewBox 属性定义。
viewBox 属性
viewBox 是 SVG 中至关重要的属性,它定义了 SVG 画布上可见区域的坐标系。viewBox 允许独立于 SVG 的 width 和 height 来定义图形的坐标空间。这创建了一个用户坐标系,使得图形可以独立于视口尺寸进行缩放。
语法
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(视口)。浏览器会自动将400x200的viewBox缩放到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>平移效果
通过调整 viewBox 的 min-x 和 min-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> 的 x 和 y 属性定义了它在父坐标系中的位置。
基本示例
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 常用于:
- 创建独立的坐标系统: 不同部分使用不同的缩放比例
- 实现局部滚动: 在 SVG 内部创建可滚动区域
- 性能优化: 将频繁更新的部分隔离到单独的 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>