前端开发者学堂 - fedev.cn

SVG系列教程:坐标系统

发布于 大漠

SVG其实相当于一块画板,然后在这块画板上绘图形,而每个画板都会有一个坐标系统。比如说画板的原始起点,绘制图形的起始点坐标,终点坐标等。这一切的一切都离开不坐标,而这些坐标就组成了一个坐标系统。在这篇文章的所要介绍就是SVG中一个关键知识点——SVG坐标。简单点理解SVG坐标就是屏幕坐标点(从技术上讲,最初的viewport坐标系统)与任何SVG元素相关联的坐标点系统(当前用户坐标系统)。例如,一个<svg>中使用<circle>绘制的一个圆,他就使用了一个标准的笛卡尔坐标系统(Cartesian Coordinate System)。

笛卡尔坐标系统

##记忆中的坐标系统

记忆中的坐标系统(2D)就是有两根轴线(x轴和y轴),交织在一起,而他们这个交点被称为坐标原点(0,0)。沿水平方向左右延伸的这条轴,称之为水平轴(也就是x轴),而沿纵向上下延伸的这条轴,称之为垂直轴(也就是y轴)。原点沿x轴向右为正值,反之为负值;同样在y轴也是如此。如下图所示:

记忆中的坐标系统

但在设计中,坐标系统原点一般都是在屏幕的左上角处。不仿来看看制作软件中的一张平面截图:

设计中的坐标系统

而浏览器中也有一个坐标系统,他和制作图软件中的长得非常相似,原点都在屏幕左上角处:

浏览器中的坐标系统

这似乎脱离今天要说的主题了一样,我们还是回到SVG的坐标系统中来吧。

##Viewport

在Web页面开发中,Viewport严格来讲就是浏览器的窗口。他不是一个HTML的概念,也就无法通过CSS修改Viewport。对于桌面浏览器,Viewport其实就是浏览器的宽度高度,而在移动端设备浏览器中,Viewport就稍加复杂。(感兴趣的可以点击这里阅读)。

在SVG中也有一个Viewport,而这个viewport被视为SVG的可见区域大小,将其想象成画布或者画板大小。在<svg>元素中通过设置其widthheight属性来控制SVG的viewport大小。其中widthhegiht的属性值可以直接是一个简单的数字,也可以指定具体的单位。如果没有指定单位,那么将会认其为“像素px”为单位。

单位 含义
em 相对于父元素的字体大小
ex 相对于小写字母"x"的高度
px 相对于屏幕分辨率而不是视窗大小:通常为1个点或1/72英寸
in inch, 表英寸
cm centimeter, 表厘米
mm millimeter, 表毫米
pt 1/72英寸
pc 12点活字,或1/12点
% 相对于父元素。正常情况下是通过属性定义自身或其他元素

其实,SVG中的Viewport还包含一些其他相关的知识,而这些知识对于使用SVG都是非常重要的,感兴趣可以看看@张鑫旭大写师的一篇相关教程《理解SVG的viewport,viewBox,preserveAspectRatio》。

##SVG坐标系统

理解了一SVG的viewport之后,我们来深入了解SVG的从标系统。SVG的坐标系统分为三种类型:

  • 最初坐标系统
  • 嵌套坐标系统
  • 转换坐标系统

接下来,我们一起来了解SVG这三种坐标系统。

###最初坐标系统

SVG的最初坐标签系统和viewport的坐标系统是相同的,都是在左上角原点处,沿y轴向下和x轴向右延伸。也就是说,SVG的坐标系统类似于Viewport的坐标系统,原点(0,0)在左上角处,不管使用单位还是不使用单位,其都是沿y轴向下垂直延伸,沿x轴向右延伸。如下图所示:

最初坐标系统

假设你有一个SVG:

<svg width="300" height="300">
</svg>

那么这个SVG的大小是300*300,其是由坐标(0,0)、(300,0)、(300,300)和(0,300)组成的一个矩形画布:

最初坐标系统

这里没有设置具体的单位值,表示的就是SVG画布大小是300*300个单位,默认情况下就是px

为了让大家更好理解SVG最初坐标,来看几个示例。

下面的示例,创建了一个300*300像素(px)的SVG,然后使用<rect><svg>中绘制了一个矩形,这个矩形的起始点是(20,20),其宽度是100px,高度是50px。如下:

<svg width="300" height="300">
  <rect x="20" y="20" width="100" height="50" style="stroke: #f36; fill: rgba(123,123,23,.5);"/>
</svg>

效果如下:

即使SVG的Viewport没有设置具体的单位,<svg>中的图形元素(比如<rect><line>等)也可以设置具体的单位值,比如:

<svg width="300" height="300">
  <rect x="20" y="20" width="50mm" height="50mm" style="stroke: #f36; fill: rgba(123,123,23,.5);"/>
</svg>

效果如下:

另外,<svg>设置了Viewport的具体单位,并不会影响坐标没有单位的子元素。比如下面的示例,<svg>的Viewport设置了单位为mm,但矩形<rect>绘制还是按像素的坐标在绘制。

<svg width="100mm" height="100mm">
  <rect x="20" y="20" width="50" height="50" style="stroke: #f36; fill: rgba(123,123,23,.5);"/>
</svg>

效果如下:

###嵌套坐标系统

<svg>元素中可以嵌套<svg>元素。外面的<svg>创建一个Viewport和坐标系统,而且嵌套在里面的<svg>也可以创建一个Viewport和坐标系统。这种方式就是在大的画布中绘制一个小的画布,我们就可以使用这种技术实现下面的效果:

而不是先绘制矩形,然后绘制圆形,再调整圆形到指定的位置,我们只需采取以下步骤:

  • 首先创建一个<svg>,用于绘制外面的大画布
  • 在外面的<svg>里使用<rect>绘制一个蓝色矩形
  • <svg>中嵌套一个<svg>,并且给里面的<svg>设置适当的preserveAspectRatio属性
  • 在里面的<svg>中使用<circle>绘制一个圆

这个简单的示例典型向大家阐述了SVG中嵌套的坐标系统。接下来,花点时间来阐述这个过程:

首先使用<svg>创建了一个主画布,并且使用<circle>在这个画布中绘制了一个圆:

<svg width="600px" height="300px" viewBox="0 0 250 250">
  <circle cx="35" cy="35" r="35" style="stroke: black; fill: none;"/>
</svg>

效果如下;

接下来使用<rect>在主画布<svg>中绘制了一个蓝色矩形:

<svg width="600px" height="300px" viewBox="0 0 250 250">
  <circle cx="35" cy="35" r="35" style="stroke: black; fill: none;"/>
  <rect x="150" y="50" width="200" height="100" style="stroke: blue; fill: none;"/>
</svg>

效果如下:

现在添加一个<svg>元素,并且交这个<svg>元素嵌套在前一个<svg>元素中,同时给其指定viewBoxwidthheightpreserveAspectRatio属性值。你还可以为其指定xy属性值(如果不显式的声明xy属性值,将默认其值为0)。从而生成一个新的Viewport。

<svg width="600px" height="300px" viewBox="0 0 250 250">
  <circle cx="35" cy="35" r="35" style="stroke: black; fill: none;"/>
  <rect x="150" y="50" width="200" height="100" style="stroke: blue; 
        fill: none;"/>
  <svg x="150px" y="50px" width="200px" height="100px" viewBox="0 0 125 125" preserveAspectRatio="xMaxYMax meet">
  </svg>
</svg>

效果如下:

从效果中看不到任何的变化,其实在上面的代码中,将内嵌的<svg><rect>重叠在一起。

建立这种嵌套的<svg>元素的新坐标,仅从视觉上并看不出任何的不一样,但它允许你添加新的元素,比如这个示例中,在里面添加一个<circle>,就能立马体会到其不一样的好处了:

<svg width="600px" height="300px" viewBox="0 0 250 250">
  <circle cx="35" cy="35" r="35" style="stroke: black; fill: none;"/>
  <rect x="150" y="50" width="200" height="100" style="stroke: blue; 
        fill: none;"/>
  <svg x="150px" y="50px" width="200px" height="100px" viewBox="0 0 125 125" preserveAspectRatio="xMaxYMax meet">
    <circle cx="35" cy="35" r="35" style="stroke: black; fill: rgba(0,0,0,.5);"/>
  </svg>
</svg>

最终效果如下:

###转换坐标系统

转换坐标系统比前面介绍的最初坐标系统,嵌套坐标系统要复杂的多,里面还涉及到数学矩阵相关知识,在这篇文章中暂不做这方面的阐述,在后面我们将会一篇专门的文章来介绍SVG的转换坐标系统。

##总结

文章主要介绍了SVG的坐标系统相关知识,详细介绍了SVG中的最初坐标系统和嵌套坐标系统。其实除了这两个坐标系统之外还有一个转换坐标系统,而这个坐标系统在制作SVG相关动画效果起着相当关键作用。所以也是学习SVG知识必可不可缺的一部分。但在这篇文章并没有以过多的篇幅来阐述相关知识,因为后面将专门用一篇文章来阐述SVG中的变换坐标系统。

上一篇