- 发布于
Svg基础之坐标系
- Authors
- Name
- 田中原
SVG坐标系统
今天要理清的几个概念
- 画布
- ViewBox 用户坐标 (视图框、视框、视野、视盒)
- ViewPort 视口 (视窗、视口、视区)
- preserveAspectRatio
1. 画布
一个svg标签,就是一个svg的画布
画布的坐标系。0,0是在画布正中间的
画布是没有边界的,无限大的。你可以随意画图在上面。
2. ViewBox
我们可以把ViewBox,看作是一个相机。SVG画布的大小是无限的。但是我们只会展示这个svg画布的一部分给用看。 这个我们用来展示给用户的区域就是ViewBox。
假设我们viewBox宽为100px,高为100px
<svg viewBox="0,0,100,100"></svg>
修改viewBox属性 (指定用户坐标系)
viewBox的四个参数
x:左上角横坐标,y:左上角纵坐标,width:宽度,height:高度
我们调整viewBox参数,可以使两个图形全部展示出来
<svg viewBox="75,75,150,150"></svg>
3. viewPort
按照我们前面的理解。我们现在用相机拍了一个照片,那么我们还需要一个容器来展示这个相片。 大家可以理解为相框。
<svg height="150" width="150" viewBox="75,75,150,150"></svg>
height``width
的单位不写的时候默认是px
单位 | 含义 |
---|---|
em | 相对于父元素的字体大小 |
ex | 相对于小写字母"x"的高度 |
px | 相对于屏幕分辨率而不是视窗大小:通常为1个点或1/72英寸 |
in | inch, 表英寸 |
cm | centimeter, 表厘米 |
mm | millimeter, 表毫米 |
pt | 1/72英寸 |
pc | 12点活字,或1/12点 |
% | 相对于父元素。正常情况下是通过属性定义自身或其他元素 |
viewPort和viewBox的关系(假设viewPort和viewBox宽高比一致)
viewBox = viewPort (上面已经展示了)
viewBox < viewPort
- viewBox > viewPort
viewPort的单位不为px时。
<svg width="70mm" height="70mm" viewBox="0,0,100,100" style="border: 1px solid black;">
<rect x="10" y="10" width="50" height="50" style="fill:none; stroke: black;stroke-width:1px;" />
</svg>
图中svg实际每1px的实际渲染结果是(70/100)0.7毫米 正方形的左上角距离viewPort左上角的距离为7毫米
总结: 当不设置viewBox属性时,默认坐标就是像素。viewPort的宽高是多少像素,显示区域默认坐标系的宽高就是多少。
设置viewBox属性时,实际上修改的是坐标系。 viewPort和viewBox同时决定了坐标系的刻度。
网络上的文章有的讲解为多个坐标系,最少的也会拆为视窗坐标系,用户坐标系。多个坐标系的说法反而让我阅读的时候产生混乱。 我个人比较赞同svg精髓里的说法,我们实际上只有一个坐标系,默认用户坐标,而设置viewBox只是为视口指定了用户坐标。
4. preserveAspectRatio
preserve [prɪˈzɜːrv] vt. 保存;保护;维持;腌;禁猎
aspect [ˈæspekt] n. 方面;方向;形势;外貌
ratio [ˈreɪʃioʊ] n. 比率,比例
当viewPort和viewPort的宽高比不一致的时候。会有三种处理方法
按最小尺寸等比缩放图形,保持viewBox的宽高比,使图形完全填充视口。 在第一种情况下,由于viewBox在某一方向比视口小,所以我们必须指定将viewBox放置在哪里。
按较大的尺寸等比例缩放图形并裁剪掉超出视口的部分。 在第二种情况下,由于viewBox在某一方向比视口大,我们必须指定哪个区域被剪切掉。
不保留宽高比,拉伸和挤压绘图以使其恰好填充视口
preserveAspectRatio是svg元素上的属性
preserveAspectRatio决定了我们如何在viewPort中显示viewBox
preserveAspectRatio的格式
preserveAspectRatio="alignment[meet|slice]"
其中alignment指定轴和位置,下面是alignment的可选值
要注意y对齐方式由大写字母开始,因为x对齐方式和y对齐方式被连接成为一个单词。
而使用meet
或slice
决定了是viewBox适配视口
还是viewBox填充视口
如果没有指定preserveAspectRatio,其默认值为xMidYMid, meet
它会缩小图像以适配可用的空间,并且使它水平和垂直居中。
使用 meet 说明符
直接使用《svg精髓》例子展示,使用meet的情况
假设我们有一个viewBox="0 0 90 90", viewPort为宽为45像素、高为135像素的
<!-- 高视口 -->
<svg preserveAspectRatio="xMinYMin meet" viewBox="0 0 90 90" width="45" h eight="135">
<svg preserveAspectRatio="xMidYMid meet" viewBox="0 0 90 90" width="45" h eight="135">
<svg preserveAspectRatio="xMaxYMax meet" viewBox="0 0 90 90" width="45" h eight="135">
<!-- 宽视口 -->
<svg preserveAspectRatio="xMinYMin meet" viewBox="0 0 90 90" width="135" height="45">
<svg preserveAspectRatio="xMidYMid meet" viewBox="0 0 90 90" width="135" height="45">
<svg
preserveAspectRatio="xMaxYMax meet"
viewBox="0 0 90 90"
width="135"
height="45"
></svg>
</svg>
</svg>
</svg>
</svg>
</svg>
这个时候viewBox保持宽高比的状态下放入viewPort中去。
<svg width="200" height="200" viewBox="0, 0, 200, 400" style="border: 1px solid black;">
<rect x="0" y="0" width="200" height="400" style="stroke: red; fill: none" />
</svg>
这里一定要注意我们对齐方式对齐的是什么?
本质上我们viewBox设定的坐标系,根据viewPort适配了。坐标原点(0,0)不再是我们以为的左上角了
<svg width="200" height="200" viewBox="0, 0, 200, 400" style="border: 1px solid black;">
<rect x="0" y="0" width="200" height="400" style="stroke: red; fill: none" />
<rect x="200" y="200" width="100" height="100" style="stroke: red; fill: none" />
</svg>
摒弃掉我们相机的比喻,实际上是修改的坐标系。
使用 slice 说明符
还是最开始的假设。这时preserveAspectRatio
第二个参数设置为slice
假设我们有一个viewBox="0 0 90 90", viewPort为宽为45像素、高为135像素的
<!-- 高视口 -->
<svg preserveAspectRatio="xMinYMin slice" viewBox="009090" width="45" height="135">
<svg preserveAspectRatio="xMidYMid slice" viewBox="009090" width="45" height="135">
<svg preserveAspectRatio="xMaxYMax slice" viewBox="009090" width="45" height="135">
<!-- 宽视口 -->
<svg preserveAspectRatio="xMinYMin slice" viewBox="009090" width="135" height="45">
<svg preserveAspectRatio="xMidYMid slice" viewBox="009090" width="135" height="45">
<svg preserveAspectRatio="xMaxYMax slice" viewBox="009090" width="135" height="45"></svg>
</svg>
</svg>
</svg>
</svg>
</svg>
有了前面的经验,slice也更好理解一些。
整个设置为none
<svg preserveAspectRatio="none" viewBox="0 0 90 90" width="45" height="135">
<svg preserveAspectRatio="none" viewBox="0 0 90 90" width="135" height="45"></svg>
</svg>