1

作者:DDU(沪江前端开发工程师)
本文是原文翻译,转载请注明作者及出处。

简介

Scalable Vector Graphics (SVG)是在XML中描述二维图形的语言。这些图形由路径,图片和(或)文本组成,并能够在不失真的情况下任意变换尺寸。
本书主要介绍了内联SVG,它是指在HTML中编写的嵌入式代码,以便在浏览器中生成这些图形。

以这种方式使用SVG有许多优点,包括为了交互目的访问所有图形的各个部分,支持访问 SVG 文档构成的 DOM 节点树,查询、修改 DOM 节点的属性,提升用户可访问性。

先介绍基本组织和简单形状,再继续描述SVG坐标系或“Canvas”,然后用它绘制图形的内部和/或边框,变换,以及使用和操作图形文本。通过渐变和模式等更高级的功能来总结。

这个指南快速且详细的介绍内联式SVG以及所有涵盖的可使用的功能,有助于你学习SVG。 它面向设计师和开发人员,希望以最可行的方式将SVG添加到他们的工作流程中。

从小笔画细节到开始使用手工制作的模式,本指南旨在成为一个围绕“go-to”编写SVG的参考。

前言

本“口袋指南”只针对已经有一些HTML和CSS基础的人,在你喜爱的浏览器中绘制SVG之前最好知道一些额外的知识, 例如:在SVG中正确渲染的信息,如何让你的图形更容易访问,以及何时何处使用矢量图形软件。

如何使用SVG

有许多方法可以把SVG插入到你的项目:内联、img标签、背景图、<object>或者作为Data URI’s。我们主要介绍内联SVG的使用方法,包括如何在结构清晰的HTML文档中编写SVG代码。

尽管我们只是介绍了内联SVG的使用方法,但在某些特定情况下,其他方法也许会更好。例如,如果你不需要图形本身的编辑功能或访问其各个部分,则用<img>标签可能更适合。

矢量图形软件

当你想要创建几乎不可能手写的更复杂的图形时,矢量图形软件更实用。你可以将Adobe Illustrator, Inkscape, Sketch, iDraw,和 WebCode这些工具放到你的SVG技能包中。

可以用这些工具直接导出SVG代码并嵌入你的HTML。我们过一会再讨论这个。

页面上的SVG

为了简洁起见,SVG DOCTYPE,版本号,xmlns和xml:space在这本书中不会被提到。

这些属性专注于SVG的版本和文档的命名空间。只要记住这一点,你不需要这些属性就能成功地在浏览器中呈现图形。 如下面这个例子,在Illustrator生成的SVG代码时不要吃惊:

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"></svg>

在大多数情况下,<svg>元素中的DOCTYPE和属性不是必需的,可以删除,以缩减你的代码。

SVG用户辅助功能

使用SVG辅助功能是一个好习惯,但是为了简洁,描述和标题不会包含在整本书的代码中。

一旦你更熟练的绘制SVG,这些元素将使你的图形更能被用户接受。例如,<desc>元素中的内容允许你向屏幕阅读器的用户提供图形的详细描述。
由于SVG文本可以被检测和读取,并且可以容易地调整大小以适应特定的阅读偏好,提供了在可访问性方面优于传统的基于光栅的图像的巨大优势。

注意事项

使用之前一些更通用的注释:整本书的演示字体都可通过Google Fonts获得。虽然你可以通过font-family看到这些字体显示出来,但你不会看到获取谷歌字体时使用的相关link或@import。

示例始终使用像素和百分比作为单位标识符。 SVG支持的长度单位为:em,ex,px,pt,pc,cm,mm,in和百分比。

本书中的SVG代码可以添加到任何文本编辑器,并且在任何支持内联SVG的浏览器中查看。通常情况下浏览器支持对于SVG非常强大,但是有更多高级的特性(例如渐变)时这种支持会变得弱一些。Can I Use是一个检查功能支持的实用网站,但实践才是检验真理的唯一方法。

你也可以复制代码,通过CodePen把它放在一个HTML部分,就能立即在屏幕上看到你的图形。我说的可能不够好,但它是我对SVG感兴趣的第一因素。练习,修改甚至失败是我最喜欢的学习方式。

最终,由于篇幅限制,一部分例子会有图形代码注释,其他不想关的将被省略。

<svg>
    <!--<path d=<this path is commented out> />-->
</svg>

第一节:篇章组织

SVG详细信息位于<svg>元素中。此元素中有几个属性,可以自定义你的图形“canvas”。虽然这些属性对于呈现图像不是完全必要的,但是在跨浏览器执行时忽略它们可能使更复杂的图形易受攻击,并且使得它们容易不按预期进行呈现。

如上所述,内联图形可以“手动”编写,或者通过访问由矢量图形软件生成的XML代码来嵌入。因为这些图形元素的顺序决定了它们的堆叠顺序,所以无论哪种方式,正确的组织和结构对于编写高效的SVG代码至关重要的。

组织和语义

SVG文档片段由<svg>元素中包含的任意数量的SVG元素组成。本文档中的组织是至关重要的。文档中的内容可以快速扩展,正确的组织提高了可访问性和效率,使作者和用户都受益。

本节将介绍编写SVG的关键 - <svg>元素 - 并查看帮助初始文档设置的一些常见属性。

svg 元素

<svg>元素归属于容器和结构元素,在文档内允许嵌套使用独立的SVG片段。每个独立的片段都有自己的坐标系。

此元素中使用的属性(如width,height,preserveAspectRatio和viewBox)定义正在写入图形的画布。

当从某些矢量软件获得SVG代码时,在<svg>元素中有很多附加信息,例如SVG版本号(指示正在使用的SVG语言版本)和DOCTYPE。正如我已经提到的,这些信息不会包括在本指南的示例中,缺少它们不会阻止你的图形在屏幕上呈现。

g 元素

g元素是组合相关图形的容器元素。将此元素与描述和标题元素结合使用提供图形的相关信息,并将相关图形组件分在同一组在一起提高访问性。 此外,通过相关元素分在同一组,可以将它们看作一个整体与各个独立的部分。移动这些元素尤其方便,例如,可以移动整个组。 不包含在g中的任何元素则认为有它们自己的组。

use 元素

<use>元素允许您在整个文档中重复使用元素。此元素中可以包含其他属性,例如x,y,width和height,这些属性定义图形在坐标系中的详细映射位置。 在这里使用xlink:href属性可以调用要重用的元素。例如,如果存在需要重新使用的苹果的图像的“apple”的id的<g>,则该图像可以由<use>:<use x =“50”y =“50” xlink:href =“#apple”/>。 这个元素作为一个重要的时间保护程序帮助压缩代码。

defs 元素

虽然<use>允许重用已经渲染的图形,但<defs>元素中的图形不会渲染到画布上,而是能够被引用,然后通过使用xlink:href来渲染。 图形在<defs>中定义,然后可以通过引用该图形的id在整个文档中使用。 例如,下面的代码绘制一个非常简单的矩形渐变:

<svg>
    <defs>
        <linearGradient id="Gradient-1">
            <stop offset="0%" stop-color="#bbc42a" />
            <stop offset="100%" stop-color="#765373" />
        </linearGradient>
    </defs>
    <rect x="10" y="10" width="200" height="100" fill= "url(#Gradient-1)" stroke="#333333" stroke-width="3px" />
</svg>

<defs>除非引用其唯一的id来调用,不然内容没有直观的输出,在这个实例中通过矩形的fill属性完成内容渲染。

symbol 元素

<symbol>元素类似于<g>,因为它提供了一种组元素的方法,但是,如果没有使用<use>元素,<symbol>中的元素没有可视化输出(如<defs>)。 它也不同于<g>元素,<symbol>建立自己的坐标系,与渲染的视口分开。 SVG视口和viewBox共同建立被映射的图形的坐标系统,将进一步介绍不同的部分。

堆叠顺序

HTML中的其他元素的堆叠顺序可以CSS中的z-index操纵,但SVG不能。 SVG元素的堆叠顺序完全取决于它们在文档片段中的位置。 下面的葡萄和西瓜在同一个<svg>元素中。西瓜出现在葡萄前面,因为文档中包含组成西瓜的路径的组被列在葡萄之后。

<svg>
    <g class="grapes">
        <!--<path <stem path> />-->
        <!--<path <grapes path> />-->
        <!--<path <leaf path> />-->
    </g>
    <g class="watermelon">
        <!--<path <outside path> />-->
        <!--<path <inside path> />-->
        <!--<path <seeds path> />-->
    </g>
</svg>

clipboard.png

如果包含葡萄的组被移动到文档的末尾,它将出现在西瓜的前面。

<svg>
    <g class="grapes">
        <!--<path <stem path> />-->
        <!--<path <grapes path> />-->
        <!--<path <leaf path> />-->
    </g>
    <g class="watermelon">
        <!--<path <outside path> />-->
        <!--<path <inside path> />-->
        <!--<path <seeds path> />-->
    </g>
</svg>

clipboard.png

这种定型的堆叠顺序的方法也适用于组内的每一个元素。例如,将葡萄的茎的路径移动到组的末尾将导致茎在顶部。

clipboard.png

第二节:基本形状和路径

当你需要在HTML中使用更复杂的内联SVG图形时就没有办法再手工编写了。那些更复杂的图形可以使用矢量软件创建,但现在我们来学习下手动编码的基础。

基本形状

SVG包含以下基本形状元素集:矩形,圆形,椭圆形,直线,折线和多边形。每个元素在渲染之前需要一些属性,如坐标和大小等详细信息。

矩形

<rect>元素定义一个矩形。

<svg>
    <rect width="200" height="100" fill="#BBC42A" />
</svg>

clipboard.png

width和height属性确定矩形的大小,而fill则设置形状的内部颜色。数值默认为pixels,当未指定时,fill将默认为黑色。 其他属性还有x和y坐标。这些值将图形沿<svg>元素对应的轴移动相应的距离。

也可以通过指定rx和ry属性中的值来创建圆角。例如,rx =“5”ry =“10”将产生具有5px半径的角的水平边,以及具有10px半径的角的垂直边。

圆形

基于中心点和外半径设置<circle>元素。

<svg>
    <circle cx="75" cy="75" r="75" fill="#ED6E46" />
</svg>

clipboard.png

cx和cy坐标建立圆的中心相对于由<svg>设置的工作空间尺寸的位置。
r属性设置外半径的大小。

椭圆

<ellipse>元素基于中心点和两个半径定义椭圆。

<svg>
    <ellipse cx="100" cy="100" rx="100" ry="50" fill="#7AA20D" />
</svg>

clipboard.png

当cx和cy值基于到SVG坐标空间中的像素距离建立中心点时,rx和ry值定义形状的边的半径。

直线

line元素定义具有开始点和结束点的直线。

clipboard.png

x1和y1值确定线的开始坐标,而x2和y2值确定线的结束坐标。

折线

<polyline>元素定义了一组相连的直线段,通常构成开放形状(不连接的开始点和结束点)。

<svg>
    <polyline points="0,40 40,40 40,80 80,80 80,120 120,120 120,160" fill="white" stroke="#BBC42A" stroke-width="6" />
</svg>

clipboard.png

在整个形状中points的值在x和y轴上建立形状的位置,并且在整个值列表中被分组为x,y。不能使用奇数点。

多边形

<polygon>元素定义由连接的线组成的闭合形状。

<svg>
    <polygon points="50,5 100,5 125,30 125,80 100,105 50,105 25,80 25,30" fill="#ED6E46" />
</svg>

clipboard.png

多边形形状的点通过八组的x,y值来定义。

该元素还可以根据点的数量产生其他闭合形状。

路径元素

SVG路径表示形状的轮廓。此形状可以填充,描边,并用于导航文本和/或用作剪切路径。 当涉及许多曲线时,这个路径会变得非常复杂。然而,理解工作原理和涉及的语法将有助于管理这些特定路径。

path data

路径数据包含在<path>元素内的d属性中,定义了形状的轮廓:<path d =“<path data specifics>”/>。 d属性中的这些数据说明了路径的moveto,line,curve,arc和closepath指令。

下面的<path>详细信息定义了青柠图形的路径细节:

<svg width="258px" height="184px">
    <path fill="#7AA20D" stroke="#7AA20D" stroke-width="9" stroke-linejoin="round" d="M248.761,92c0,9.801-7.93,17.731-17.71,17.731c-0.319,0-0.617,0-0.935-0.021c-10.035,37.291-51.174,65.206-100.414,65.206 c-49.261,0-90.443-27.979-100.435-65.334c-0.765,0.106-1.531,0.149-2.317,0.149c-9.78,0-17.71-7.93-17.71-17.731 c0-9.78,7.93-17.71,17.71-17.71c0.787,0,1.552,0.042,2.317,0.149C39.238,37.084,80.419,9.083,129.702,9.083    c49.24,0,90.379,27.937,100.414,65.228h0.021c0.298-0.021,0.617-0.021,0.914-0.021C240.831,74.29,248.761,82.22,248.761,92z" />
</svg>

clipboard.png

moveto

moveto命令(M或m)建立一个新的点,就像提起一支钢笔,并在纸上一个新位置绘制。包括路径数据的代码行必须以moveto命令开始,如上面的例子所示。 moveto命令跟在初始化路径之后,代表新子路径的开始和复合路径的创建。这里的大写字母M表示绝对坐标,小写字母m表示相对坐标。

closepath

closepath(Z或z)表示当前子路径的结束,并从该点到路径的初始点绘制直线。 如果closepath之后紧跟着一个moveto,这些moveto坐标表示下一个子路径的开始。如果这个相同的closepath之后是moveto之外的任何东西,则下一个子路径从当前子路径的点开始。 这里大写或小写z没有区别。

lineto

lineto命令从当前点到新点绘制直线。

L, l

L和l命令从当前点绘制一条线到下一个提供的点坐标。这个新点然后变成当前点,以此类推。 大写L表示绝对定位,而小写l是相对定位。

H, h

H和h命令从当前点绘制水平线。
大写H表示绝对定位,而小写h是相对定位。

V, v

V和v命令从当前点绘制垂直线。
大写V表示绝对定位,而小写v是相对定位。

曲线命令

有三组命令绘制曲线路径:CubicBézier(C,c,S,s),二次贝塞尔(Q,q,T,t)和椭圆弧(A,a)。 以下曲线部分将介绍每条曲线命令的基本概念,和映射的详细信息,然后提供一个图表供进一步了解。

Cubic Bézier

C和c CubicBézier命令从当前点绘制曲线,使用(x1,y1)参数作为曲线开始处的控制点,(x2,y2)作为结束处的控制点,定义形状细节曲线。

S和s命令还绘制立方贝塞尔曲线,但在这种情况下,存在第一控制点是第二控制点的反射的假设。 下面的代码绘制了一个基本的CubicBézier曲线:

clipboard.png

<svg>
    <path fill="none" stroke="#333333" stroke-width="3" d="M10,55 C15,5 100,5 100,55" />
</svg>

该曲线的第一和最后一组值将影响其开始和结束位置,两个中心值将影响曲线本身在开始和结束时的形状和定位。 S和s命令也绘制立方贝塞尔曲线,但在这种情况下,假设第一个控制点是前一个C命令的最后一个控制点的反映。则会作为相对于S命令的开始点。

clipboard.png

大写字母C表示绝对定位,而小写字母c是相对定位。S和s也是一样。

Quadratic Bézier

二次贝塞尔曲线(Q,q,T,t)类似于立方贝塞尔曲线,除了它只有一个控制点。

clipboard.png

以下代码绘制了一个基本的二次贝塞尔曲线:

<svg>
    <path fill="none" stroke="#333333" stroke-width="3" d="M20,50 Q40,5 100,50" />
</svg>

操作第一个和最后一组值M20,50和100,50会影响曲线起点和终点的位置。中心值集Q40,5定义曲线的控制点,确定其形状。

Q和q使用(x1,y1)作为控件从初始点到终点绘制曲线。 T和t通过假设控制点是相对于新的T或t命令的开始点的先前列出的命令的控制的反映,从初始点到终点绘制曲线。

clipboard.png

大写的Q信号表示绝对定位,而小写的q是相对定位。T和t也是一样。

Elliptical Arc

椭圆弧(A,a)定义椭圆的线段。这些段通过A或命令创建,通过指定起点,终点,x和y半径,旋转和方向创建弧。

下面是一个基本椭圆弧的代码:

<svg>
    <path fill="none" stroke="#333333" stroke-width="3" d="M65,10 a50,25 0 1,0 50,25" />
</svg>

该路径中的第一和最后一组值,M65,10和50,25表示初始和最终坐标,而第二组值定义两个半径。 1,0(大弧标志和顺时针标志)的值确定如何绘制圆弧,因为这里有四个不同的选项。 下图显示了四个弧选项以及大弧标志值和顺时针标志值对弧段的最终渲染的影响。

clipboard.png

矢量软件嵌入

矢量图形软件可以制作更复杂的形状和路径,同时可以导出SVG代码在其他地方使用和操作。

一旦图形完成,生成的XML代码可以被复制并嵌入到HTML中,图形越复杂代码越长。分解SVG的每个部分并且运用适当的组织元素可以极大地帮助引导和理解这些复杂和冗长的代码。

这里是一些樱桃的SVG代码图像,添加了引导类:

<svg width="215px" height="274px" viewBox="0 0 215 274">
    <g>
        <path class="stems" fill="none" stroke="#7AA20D" stroke-width="8" stroke-linecap="round" stroke-linejoin="round" d="M54.817,169.848c0,0,77.943-73.477,82.528-104.043c4.585-30.566,46.364,91.186,27.512,121.498" />
        <path class="leaf" fill="#7AA20D" stroke="#7AA20D" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" d="M134.747,62.926c-1.342-6.078,0.404-12.924,5.762-19.681c11.179-14.098,23.582-17.539,40.795-17.846 c0.007,0,22.115-0.396,26.714-20.031c-2.859,12.205-5.58,24.168-9.774,36.045c-6.817,19.301-22.399,48.527-47.631,38.028 C141.823,75.784,136.277,69.855,134.747,62.926z" />
    </g>
    <g>
        <path class="r-cherry" fill="#ED6E46" stroke="#ED6E46" stroke-width="12" d="M164.836,193.136 c1.754-0.12,3.609-0.485,5.649-1.148c8.512-2.768,21.185-6.985,28.181,3.152c15.076,21.845,5.764,55.876-18.387,66.523 c-27.61,12.172-58.962-16.947-56.383-45.005c1.266-13.779,8.163-35.95,26.136-27.478   C155.46,191.738,159.715,193.485,164.836,193.136z" />
        <path class="l-cherry" fill="#ED6E46" stroke="#ED6E46" stroke-width="12" d="M55.99,176.859 c1.736,0.273,3.626,0.328,5.763,0.135c8.914-0.809,22.207-2.108,26.778,9.329c9.851,24.647-6.784,55.761-32.696,60.78 c-29.623,5.739-53.728-29.614-44.985-56.399c4.294-13.154,15.94-33.241,31.584-20.99C47.158,173.415,50.919,176.062,55.99,176.859z" />
    </g>
</svg>

clipboard.png

svg元素中的属性定义工作区,或图形的“画布”。叶和茎在一个g(组)内,而樱桃在另一个。数字字符串定义图形将采用的路径,fill和stroke属性设置背景和边框的颜色。

将这个代码复制下来,它会通过一个SVG优化器在被放置在HTML之前,以助于消除不必要的代码和间距,进而大大缩小文件。 关于这个方面Peter Collingridge的SVG Optimiser和SVGO也是非常有用的工具。

致谢

我用这一整节的内容来表达对你们特别的感谢:

CSS-Tricks(http://css-tricks.com/)
Lincoln Loop(http://lincolnloop.com/)
Designmodo(https://designmodo.com/)
Tahoe Partners(http://www.tahoepartners.com/)
Una Kravets(https://twitter.com/Una)

原文地址:http://svgpocketguide.com/book/

剩余部分将在编写SVG的口袋指南(下)中展示,敬请期待。

iKcamp原创新书《移动Web前端高效开发实战》已在亚马逊、京东、当当开售。

>> 沪江Web前端上海团队招聘【Web前端架构师】,有意者简历至:zhouyao@hujiang.com <<


iKcamp
3.8k 声望666 粉丝

iKcamp由热爱原创和热翻译的小伙伴发起,成员来自美团点评、沪江等。成立于2016年7月,"iK"代表布兰登·艾克(JavaScript之父)。 追随JavaScript这门语言所秉持的精神,崇尚开放和自由的我们一同工作、分享、创作...