3.SVG坐标系

SVG世界是一个无限画布,视窗(Viewport)定义了感兴趣的区域。通过<svg>元素的width和height属性设定视口尺寸,单位可以是像素、厘米等。视口的左上角是坐标原点(0,0)。viewBox属性指定用户坐标系,允许自定义单位比例。preserveAspectRatio属性用于保持纵横比,可选择meet、slice或none标识符。嵌套的SVG元素创建了坐标系统层级,允许在不同区域内绘制图形。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

3. Coordinates 坐标系

SVG 的世界是一幅无限的画布(infinite canvas)。在本章,我们将弄清楚,如何告诉浏览程序,你对 canvas 的哪一部分感兴趣,它的尺寸是多少,以及如何定位该区域的点。

The Viewport 视窗

文档打算使用的 canvas 区域称为视窗(Viewport)。你通过 <svg> 元素的 width 和 height 属性确定 viewport 的尺寸。每个属性的值可以是单纯的一个数字,在这种不带单位的情况可以是只是,数字被认为是以像素为单位。也就是用户坐标系(user coordinates)中指定的单位。你也可以用一个数字,后面跟一个单位标识符(unit identifier),来指定 width 和 height,单位可以是下面中的一个:

  • em

默认字体的字体大小(font size),通常相当于文本行的高度。

  • ex

字母 x 的高度

  • px

Pixels 像素(在 CSS2-supporting 图形中,每英寸有 96 像素: 96 pixels per inch)

  • pt

Points(一英尺的七十二分之一: 1/72 of an inch)

  • pc

Picas(一英尺的六分之一: 1/6 of an inch)

  • cm

Centimeters 厘米

  • mm

Millimeters 毫米

  • in

Inches 英寸

可能的 SVG viewport 声明包含下面的代码:

<svg width="200" height="150">
<svg width="200px" height="150px">

这两种方式指定了一个 200像素宽,150像素高的区域。

<svg width="2cm" height="3cm">

这种方式指定了一个 2厘米宽, 3厘米高的区域。

<svg width="2cm" height="36pt">

有可能,虽然不寻常,混合使用单位。这个元素指定一个 2厘米宽,36 points 高的区域。

一个<svg>元素可以指定其 width 和 height 的百分比。当这个元素嵌套在另外一个 <svg> 元素中时,百分比以包含的元素来衡量。如果这个 <svg>
元素是 root element, 百分比以窗口的大小来衡量。你将在坐标系的嵌套体系(Nested Systems of Coordinates)中看到嵌套的 <svg> 元素。

Using Default User Coordinates 使用默认用户坐标系

查看器(viewer)设置一个坐标系统,其中水平(horizontal)或 x轴(x-coordinate),随着你往右边移动和增加,而 y轴(y-coordinate),在你竖直向下移动
的时候增加。视窗(viewport)的左上角(upper-left corner). 定义为x轴坐标和y轴坐标的 0 点。这个点,写成 (0, 0), 又被称为原点(origin)。坐标系
是一个纯粹的几何系统:点(point)既没有宽度也没有高度。网格线被认为是无限薄的。你可以在第四章中阅读更多关于这个的主题。

例3-1 建立了一个 100 像素宽和 100 像素高的视窗(viewport),然后在坐标点(10, 10)的地方绘制一个 50 像素宽和 30 像素高的矩形。图3-1 显示了结果,
用尺子和网格显示坐标系统。

在线例子

<svg width="200" height="200">
  <rect x="10" y="10" width="50" height="30" style="stroke: black; fill: none;"/>
</svg>

在这里插入图片描述

即使你在视窗(viewport)中不指定单位(unit),在一些 SVG shape 元素中你可能仍然要使用他们,就像例子3-2中那样,图3-2显示了结果,用尺子和网格显示坐标系统。

在线例子

<svg width="200" height="200">
  <rect x="10mm" y="10mm" width="15mm" height="10mm" style="stroke:black; fill:none;"/>
</svg>

在这里插入图片描述

Specifying User Coordinates for a Viewport 为视窗(Viewport)指定用户坐标系

在迄今为止的例子中,没有单位的数字默认使用像素为单位。有时候这不是你想要的。例如,你可能需要建立一个系统,每个用户坐标代表 1/16 厘米(我们使用这个坐标系统来证明这一点,而不是表示这是一个很好的设计典范)。在这个系统中,一个方块是 40X40 单位,表示每个边长是 2.5 厘米。

为了实现此效果,您在 <svg> 上设置了 viewBox 属性。这个属性的值包含了四个数字,表示您想要在 viewport 上显示的用户坐标系统的 最小 x 坐标,最小的 y 坐标,宽度和高度。

所以,要设置 16-units-per-centimeter 的用户坐标系,宽度为 4-centimeter, 高度为 5-centimeter, 你需要使用这个开始标签:

<svg width="4cm" height="5cm" viewBox="0 0 64 80">

例3-4给出了一幅房子的SVG图,使用新的坐标系统显示。图3-4显示了结果。网格线和灰暗的数字显示新的用户坐标系统;更明亮的数字以 1厘米的间距放置。

<svg width="4cm" height="5cm" viewBox="0 0 64 80">
   <rect x="10" y="35" width="40" height="40" style="stroke: black; fill: none;"/>
   <!-- roof -->
   <polyline points="10 35, 30 7.68, 50 35" style="stroke:black; fill: none;"/>
   <!-- door -->
   <polyline points="30 75, 30 55, 40 55, 40 75" style="stroke:black; fill: none;"/>
</svg>

在这里插入图片描述

你为 viewBox 属性指定的数字可以按逗号或空格隔开。如果 width 或 height 中的一个为 0, 您的图形都不会显示。如果给 viewBox 属性值中的 width 或 height
指定一个负数值,这是一个错误的方法。

注意:如果你仔细阅读例子3-4中的代码,你将会注意到,我们用小数值来使房子的屋顶的顶峰定位得恰到好处。SVG 中几乎所有的数字都是浮点小数。SVG查看器
需要至少支持32位精度数字,并鼓励使用更高的精度数字进行计算。事实上,您甚至可以使用科学符号在大小非常大或非常小的坐标系统中工作,所以 point 30,7.68
可以写成 3.0E+1,7,68e0。但是为了可读性和简洁性,我们并不推荐这种方式,保留科学符号,以便在真正必要的时候使用。

Preserving Aspect Ratio 保持纵横比

在之前的例子中,纵横比(aspect ratio),或者宽度和高度的比率(ratio of width to height), 视窗(viewport)和viewBox的值都相同(4/5 = 64/80)。
但是,如果本例中 viewport 和 viewbox 的纵横比不相同,会发生什么情况,在这个例子中,viewBox 的纵横比是 1:1(width 和 height 相等), 但是
viewport 的纵横比是 1:3(height 是 width 的三倍)?

<svg width="45px" height="135px" viewBox="0 0 90 90">

在这种情况下,SVG 可以做三件事情:

  • 根据图像尺寸均匀地缩放图形,以便图形将完全适合视图窗口(viewport)。在示例中,图片将成为其原始宽度和高度的一半。你将在 Using the meet Specifier
    中看到这方面的例子。

  • 根据较大的尺寸均匀地缩放图形,并切断位于视图窗口(viewport)外的部分。在示例中,图片将称为其原始宽度和高度的一倍半。你将在 Using the slice Specifier 中看到
    这方面的例子。

  • 拉伸和挤压图形,使其精确适合新的视图窗口(viewport)。(即根本不保留纵横比),你想在 Using the none Specifier 中看到详情。

在第一种情况下,因为图像在某一个维度上将会变得更小,你必须指定如何定位它。在这个例子中,这个图片将会被均匀地缩放到 width 和 height 为 45像素。
缩小的图形的宽度完全适合 Viewport 的宽度,但您现在必须决定图像是否与135像素高度的视图窗口(viewport)的顶部,中间或底部相交。

在第二中情况下,因为图像在某一个维度上将会变得更大,你必须指定要切开哪个区域。在本例中, 图片将均匀地缩放到 135像素的宽度和高度。现在图形的
高度完全适合视图窗口,但你必须决定是切掉右侧,左侧还是两侧,以适应 45像素的视图窗口宽度。

Specifying Alignment for preserveAspectRatio 保存视图的时候指定对齐

preserveAspectRatio 属性允许您指定缩放图像与视图窗口(viewport)的对齐方式(alignment)。以及你想让它达到边缘还是被切掉。这个属性的模型是:

preserveAspectRatio="alignment [meet | slice]"

其中对齐指定轴和位置,并且是表3-1中显示的组合之一。此对齐标识通过调节 x轴对齐(x-aligment) 和 y轴对齐(y-aligment) 的最小值,中值或最大值
而形成。 preserveAspectRatio 的默认值是 xMidYMid。

Y轴对齐(y-alignment)以大写字母开头,因为 x- 和 y-alignments 被关联为单个单词。

在这里插入图片描述

因此,如果你有一幅图像,它的 viewBox=“0 0 90 90”,完全适合宽 45 像素和高 135 像素的视图窗口(viewport),在视图窗口(viewport)的顶部对齐,您将编写以下代码:

<svg width="45px" height="135px" viewBox="0 0 90 90"
preserveAspectRatio="xMinYMin meet">

注意:在这种用例中,因为宽度非常合适,x-alignment 是无关紧要的;你使用 xMidYMin 或者 xMaxYMin 同样也可以得到很好的效果。然而,当您不知道视图窗口(viewport)的纵横比时,通常会使用 preserveAspectRatio。 例如,您可能需要将图像缩放以使用应用程序窗口,或者您可能让父文档的 CSS 设置 height 和 width。 在这种情况下,你需要考虑,当视图窗口太宽以及太高时,您希望如何显示图像。

如果你不指定 preserveAspectRatio, 默认的值是 xMidYMid meet,这将缩小图形以使用可用空间,并以水平和垂直为中心。

这一切都相当抽象;以下部分给出了一写具体的例子,向您展示了 alignment, meet 和 slice 的组合如何在另一部分进行交互。

Using the meet Specifier 使用 meet 标识符

示例3-5中的起始 <svg> 标签均使用 meet specifier。

示例3-5. Use of meet specifier

<!-- tall viewports -->
<svg preserveAspectRatio="xMinYMin meet" viewBox="0 0 90 90" width="45" height="135">
<svg preserveAspectRatio="xMidYMid meet" viewBox="0 0 90 90"
width="45" height="135">
<svg preserveAspectRatio="xMaxYMax meet" viewBox="0 0 90 90"
width="45" height="135">
<!-- wide viewports -->
<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">

在这里插入图片描述

Using the slice Specifier 使用 slice 标识符

图3-6 显示了使用 slice specifier 来消除不适合 viewport 的图片部分。他们是用
示例3-6 中的 <svg> 标签创建的。

示例3-6. Use of slice specifier

<!-- tall viewports -->
<svg preserveAspectRatio="xMinYMin slice" viewBox="0 0 90 90"
width="45" height="135">
<svg preserveAspectRatio="xMidYMid slice" viewBox="0 0 90 90"
width="45" height="135">
<svg preserveAspectRatio="xMaxYMax slice" viewBox="0 0 90 90"
width="45" height="135">
<!-- wide viewports -->
<svg preserveAspectRatio="xMinYMin slice" viewBox="0 0 90 90"
width="135" height="45">
<svg preserveAspectRatio="xMidYMid slice" viewBox="0 0 90 90"
width="135" height="45">
<svg preserveAspectRatio="xMaxYMax slice" viewBox="0 0 90 90"
width="135" height="45">

本章节的线上例子,允许你体验不同的 preserveAspectRatio 选项,以切片(slice),收缩(shrink),并转移(shift) 猫,在任意大小的SVG图片上。

在线样例

在这里插入图片描述

Using the none Specifier 使用 none 标识符

最后,当 viewBox 和 viewport 没有相同的纵横比时,有第三个选项用于缩放图形。如果您指定 preserveAspectRatio=“none”, 则图形将不均匀地缩放,以便其用户坐标适合 viewport。 图3-7 显示了类似的一个 “fun-house mirror” 效果,通过样例3-7 中的 <svg> 标签产生。

<!-- tall viewport -->
<svg preserveAspectRatio="none" viewBox="0 0 90 90"
width="45" height="135">
<!-- wide viewport -->
<svg preserveAspectRatio="none" viewBox="0 0 90 90"
width="135" height="45">

在这里插入图片描述

Nested Systems of Coordinates 嵌套的坐标系统

你可以通过在该文档中再放置一个 <svg> 来随时建立一个新的 viewport 和坐标系统(system of coordinates)。效果是创建一个"迷你画布",你可以在上面画画。
我们可以使用此技术创建类似图3-5的插图。我们采取了以下步骤,而不是绘制矩形,然后在每个矩形内重新缩放和定位猫(蛮力方法):

  • 在主画布(main canvas)上绘制一个蓝色的矩形。
  • 针对每个矩形,定义一个新的 <svg> 元素,这个元素有合适的 preserveAspectRatio 属性
  • 在这个新的画布中绘制一只猫(在 <use> 中), 让 SVG 做繁重的工作。

这里有一个简化的示例,显示组画布上的圆形,然后在主画布上由蓝色矩形勾勒处的新画布内,图3-8是预期的结果。

在这里插入图片描述

首先,为主坐标系同和圆生成SVG(请注意,用户坐标与本文档中的 viewport 完全一致)。

<svg width="200px" height="200px" viewBox="0 0 200 200">
<circle cx="25" cy="25" r="25" style="stroke: black; fill: none;"/>
</svg>

结果如图3-9所示:

在这里插入图片描述

现在,绘制框的边界,显示您希望新 viewport 的位置:

<svg width="200px" height="200px" viewBox="0 0 200 200">
   <circle cx="25" cy="25" r="25" style="stroke: black; fill: none;"/>
   <rect x="100" y="5" width="30" height="80"
style="stroke: blue; fill: none;"/>
</svg>

结果如图3-10所示。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gcwVPsWX-1633925122715)(uploads/1cf3c0e9f222346bcf1a4c1bb7d5ccc2/image.png)]

现在,为这个新的 viewport 添加另外一个 <svg> element。 除了指定 viewBox, width, height, 和 preserveAspectRatio 规范, 你还需要指定 x 和 y 属性, 在封闭的 <svg> 元素中, 将建立新 viewport 的位置(如果你不给出 x 和 y 的值,据推测,他们用这个嵌套的 <svg> 设置新的坐标,不会改变 veiwport。但它确实允许你在封闭的这个新系统中添加圆形,生成如图3-8所示的结果)。

<svg width="200px" height="200px" viewBox="0 0 200 200">
<circle cx="25" cy="25" r="25" style="stroke: black; fill: none;"/>
<rect x="100" y="5" width="30" height="80"
style="stroke: blue; fill: none;"/>
<svg x="100px" y="5px" width="30px" height="80px"
viewBox="0 0 50 50" preserveAspectRatio="xMaxYMax meet">
</svg>
</svg>

通过这个嵌入的 <svg> 建立一个新的坐标系并不会改变显示效果,但它确实允许您在该新系统中添加圆形,生成如图3-8所示的结果:

<svg width="200px" height="200px" viewBox="0 0 200 200">
<circle cx="25" cy="25" r="25" style="stroke: black; fill: none;"/>
<rect x="100" y="5" width="30" height="80" style="stroke: blue;
fill: none;"/>
<svg x="100px" y="5px" width="30px" height="80px" viewBox="0 0 50 50"
preserveAspectRatio="xMaxYMax meet">
<circle cx="25" cy="25" r="25" style="stroke: black;
fill: none;"/>
</svg>
</svg>

注意:如果您想在一额外嵌套的 <svg> 元素的 preserveAspectRatio 属性上使用 meet 或者 slice 属性值。而外层的 <svg> 元素的 preserveAspectRatio 属性的值等于 “none”,结果会令你惊讶。嵌套元素 viewport 的纵横比将在母体 SVG 的挤压或拉升坐标中得到提升,可能导致图像被压缩,裁剪或缩小以适应该图像。

  • [4] In this book, coordinates are specified as a pair of numbers in parentheses, with the x-coordinate first. Thus, (10,30)
    represents an x-coordinate of 10 and a y-coordinate of 30.

  • [5] To save space, we are leaving out the <?xml …?> and lines. These are set in stone, so you can take
    them for granite.

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值