SVG 和设计工具实用指南
已发表: 2022-03-10对 SVG 有很好的理解是一项难得的技能。 令人惊讶的是,SVG 通常被视为另一种图像格式。 我们使用 SVG 是因为它的可扩展性和更小的文件大小,但实际上,SVG 远不止这些!
在本文中,我将介绍三种最流行的设计工具:Adobe Illustrator、Sketch 和 Figma。 还有其他可用的工具支持 SVG,它们可能具有其他功能并实现其他解决方案。
注:如无特别说明,本文内容均指SVG 1.1 2nd Edition。 下面讨论的一些要点不适用于 SVG 2,但是,它仍然没有达到推荐状态,使 SVG 1.1 成为最新的规范。
为什么要为设计工具烦恼?
SVG 是一种基于 XML 的标记语言,并且与任何其他编程语言一样,可以在文本编辑器中编写和编辑。 所以理论上,相对于 JPG 或 PNG 文件,我们不需要任何 GUI 软件来创建 SVG。 但是,在绝大多数情况下,使用图形设计应用程序是不可避免的。
以基于文本的格式处理复杂的形状和图形是完全可能的,但通常会非常棘手和乏味。 因此,通常的做法是使用 Adobe Illustrator、Sketch 或 Figma 等应用程序直观地设计图形,然后将它们导出为 SVG 格式。
因此,无论您是编码设计师还是有设计意识的开发人员,要熟练使用 SVG 都需要双方的一些知识:设计工具和 SVG 语言本身。 为了更好地理解两者之间的关系,让我们仔细看看图形设计应用程序必须提供什么以及它们的功能如何转化为 SVG。
基本形状
许多矢量图形是由几个基本形状组成的——分组、转换和相互组合。 下表显示了 Illustrator、Sketch 和 Figma 中可用的形状工具以及它们导出为哪些 SVG 元素。
插画家 | 草图 | 无花果 | 生成的 SVG |
---|---|---|---|
椭圆工具 | 椭圆形 | 椭圆 | <circle /> 或<ellipse /> |
矩形工具 | 长方形 | 长方形 | <rect /> |
圆角矩形工具 | 圆形 | - | <rect rx="…" /> |
线段工具 | 线 | 线 | <line /> (Illustrator 和 Figma) <path /> (素描) |
- | 箭 | 箭 | <path /> |
多边形工具 | 多边形 | 多边形 | <polygon /> (Illustrator 和 Sketch) <path /> (Figma) |
星形工具 | 星星 | 星星 | <polygon /> (Illustrator 和 Sketch) <path /> (Figma) |
- | 三角形 | - | <polygon /> |
椭圆和圆
每个设计工具中的基本形状之一是椭圆。 在 SVG 中,我们会找到一个匹配的<ellipse />
元素,它由椭圆中心的坐标( cx
和cy
)和两个半径( rx
和ry
)定义。
这是 SVG 中椭圆的样子:
<ellipse cx="400" cy="300" rx="250" ry="150"/>
非常特殊的椭圆类型是圆形。 圆是rx
和ry
半径彼此相等的椭圆。 SVG 有自己的<circle />
元素,它少了一个属性,因为只有一个半径需要考虑:
<circle cx="400" cy="300" r="250"/>
在椭圆和圆形的情况下,所有设计工具的工作方式都是一样的:Illustrator 中的Ellipse Tool 、Sketch 中的Oval工具和 Figma 中的Ellipse工具都会生成<ellipse />
元素,除非半径相等:在这种情况下,我们最终会得到<circle />
元素。
矩形和圆角矩形
所有设计工具共有的另一个基本形状是矩形。 在所有设计工具的情况下,使用矩形工具会在 SVG 中生成<rect />
元素。 一个基本的<rect />
由 4 个属性定义:它的x
和y
坐标,以及它的宽度和高度:
<rect x="150" y="100" width="500" height="400"/>
请注意,虽然<ellipse />
和<circle />
的位置是由它们的几何中心定义的,但<rect />
的位置是由其左上角的坐标定义的。
除了基本的矩形,我们经常使用圆角矩形。 在所有三个设计工具中,您可以通过在Inspector或Properties面板中应用边框半径来将矩形变成圆角矩形。
此外,在 Sketch 和 Illustrator 中,有专门用于创建圆角矩形的工具(Illustrator 中的圆角矩形工具和 Sketch 中的圆角工具)。 但是,应用了半径的常规矩形与使用圆角矩形工具绘制的圆角矩形之间没有区别。
因此,无论如何创建,都将使用以下语法导出圆角矩形:
<rect x="150" y="100" width="500" height="400" rx="30"/>
在这种情况下, rx
是负责圆角半径的属性:
带椭圆角的圆角矩形
设计工具和 SVG 之间的一个显着区别是如何定义半径。 在我们考虑的所有设计工具中,边界半径由单个变量定义。 我们可以将边框半径视为用于掩盖矩形角的小圆圈:
同时,在 SVG 中,边框半径可以由两个属性定义: rx
(如上例)和ry
。 它们允许我们创建带有椭圆角的矩形。 您可以将这样的圆角视为用作蒙版而不是圆形的椭圆:
<rect x="150" y="100" width="500" height="400" rx="40" ry="30"/>
因此,在这种情况下,SVG 为您提供了比设计工具更多的可能性。
注意:尽管它与本文的主题并不完全相关,但值得注意的是,上述差异适用于 SVG 和 HTML/CSS。 CSS 属性border-radius
用于设置节点的样式,例如 div 和 spans 也允许创建椭圆角。 您可以在下面看到一个示例。
border-radius: 10px 5% / 20px 25em 30px 35em;
斜线 ( /
) 之前的值是水平半径(相当于rx
),斜线之后的值是垂直值(相当于ry
)。
具有多个半径的圆角矩形
在设计工具中,与在 CSS 中一样,可以单独控制矩形的每个角。 换句话说,每个角都可以有自己的半径(或完全没有半径)。 SVG 中的<rect />
元素无法进行此类操作。 每个<rect />
元素只有一个rx
和一个ry
属性。 如果您创建一个矩形,其角应用了多个半径,则设计工具将生成<path />
元素而不是<rect />
元素。 我们将在下一节中更多地讨论<path />
元素。
光滑的角落
Sketch 和 Figma 不久前引入的有趣功能之一是平滑角。 简而言之,平滑的角落使用不规则的边界半径来实现看起来更自然且平滑的结果。 圆角最常见的应用是 iOS 上的应用图标和其他圆角元素。 在 iOS6 之前,Apple 在其移动平台上使用“常规”圆角,然后在 2013 年 (iOS7) 推出的大规模重新设计中切换到我们今天所说的“平滑”角。
在 Sketch 中,您可以通过在Inspector中切换圆角和平滑角来实现平滑角效果。 Figma 让您可以更好地控制拐角,因为您可以在“拐角平滑”菜单中操作平滑度。
不幸的是,这些都不能轻松转换为 SVG,因为 SVG 根本不知道平滑角的概念。 如果您尝试将具有平滑角的矩形导出到 SVG,Sketch 和 Figma 之间的操作还有一个重要区别。
Figma 会忽略平滑的角,并将矩形导出为具有圆角的常规<rect />
元素。 另一方面,Sketch 将一个具有平滑角的矩形导出为<path />
,它试图复制平滑角的真实形状。 因此 Figma 为我们提供了更差的准确性,以保持矩形为矩形,而 Sketch 则以语义和更大的文件大小为代价,以尽可能高的准确性为目标。 如果您想更好地了解这种差异意味着什么,稍后我们将深入探讨保留基本形状的利弊。
线条
下一个基本类型的元素是线。 在这种情况下,我们将一条线称为从 A 点到 B 点的一条直线。Illustrator、Sketch 和 Figma 都提供了自己的线条工具,专门用于绘制线条。 在 SVG 中,我们有一个<line />
元素。 它的四个属性是必需的:起点坐标和终点坐标:
<line x1="100" y1="100" x2="200" y2="200"/>
在导出时,Illustrator 和 Figma 将尽可能将线条导出为<line />
元素,而 Sketch 将始终将线条计算为<path />
元素。
折线
现在让我们来看看折线。 折线是一系列相连的直线。 折线在设计工具中没有专用工具。 它们可以使用钢笔工具(在 Illustrator 和 Figma 中)或使用矢量工具(在 Sketch 中)绘制。
在 SVG 中,折线是用<polyline />
元素定义的。 <polyline />
使用points
属性绘制,该属性是定义创建折线的所有点的坐标列表。 让我们看一个由三段和四个点组成的折线示例:
<polyline points="10,20 10,20 30,10 40,20" />
Illustrator 和 Sketch 将折线转换为<polyline/>
元素,而 Figma 将折线导出为<path />
s。
箭头
在所有三个工具中,您都可以控制线条的末端将它们变成箭头等。 并且所有三个工具都会将这样的线条导出为<path />
s,即使没有应用帽子,相同的形状也会被转换为<line />
s 或<polyline />
s。 是因为 SVG 不支持箭头吗? 不完全是。
实际上,SVG 规范确实包括可定制的线端,称为标记。 但是,我们提到的设计工具都没有在它们生成的 SVG 中使用标记。
<marker>
是一个单独的 SVG 元素,可以在 SVG 的<defs>
中定义,然后用于具有标记属性的<line>
、 <polyline>
和<path>
元素: marker
、 marker-start
、 marker-mid
和marker-end
. 如果您想了解有关这些属性的更多信息,我建议您查看官方 W3C 文档。
多边形和星星
我们要看的最后一个基本形状是多边形。 多边形是由直线组成的封闭形状,例如星形或六边形。 您也可以将其视为闭合的折线。 SVG 中<polygon />
元素的语法实际上与<polyline />
相同。 两者之间的唯一区别是,在<polygon />
列表中的最后一个点始终与第一个点连接,以使<polygon />
成为一个封闭的形状。
一些多边形是正多边形。 正多边形的特别之处在于它们的所有边和角都相等。 要绘制正多边形,例如六边形或五边形,您可以使用多边形工具,在 Illustrator、Sketch 和 Figma 中相同。 Illustrator 和 Sketch 中的多边形工具将在 SVG 中生成<polygon />
元素。 另一方面,在 Figma 中,所有使用多边形工具制作的形状都会产生<path />
元素。
这三个设计工具也都有专门的星形工具来绘制星形。 但是,在导出时,使用星形工具创建的形状与使用多边形工具创建的形状完全相同。 在 SVG 中,星星只是多边形,没有~~<star />~~
元素。
重要的是要记住Star和Polygon工具用于创建规则的星星和多边形,而 SVG 中的<polygon />
元素可用于任何多边形,规则的或不规则的。
条条大路通<path />
正如我们已经了解到的,在 SVG 中,有三种基本形状专门用于绘制由直线构成的形状: <line />
、 <polyline />
和<polygon />
。 但是如果我们希望我们的线条是弯曲的呢? 现在是我们谈论<path />
元素的时候了。
<path />
元素
<path />
是最通用的 SVG 元素。 它可用于绘制任何可能的线条和形状,包括但不限于上面列出的所有基本形状。 事实上,每个基本形状( <circle/>
、 <ellipse />
、 <rect />
、 <line />
、 <polyline />
、 <polygon />
)都可以描述为一个<path />
元素。 更重要的是,有许多形状可以用<path />
创建,但不能用任何其他 SVG 元素创建。 要了解有关<path />
及其语法的更多信息,我建议您查看 Chris Coyier 撰写的这篇出色的文章。
现在,我们如何在设计工具中创建<path />
元素? 首先,正如我们在上面了解到的,使用形状工具创建的一些层计算到<path />
元素,即使它们理论上可能是其他元素(例如 Figma 将所有多边形导出为<path />
s,即使它们本来可以是定义为<polygon />
s。然后,我们使用钢笔工具或矢量工具绘制的所有其他不规则形状都必须导出为<path />
,因为没有其他 SVG 元素可以定义它们。最后,在 Sketch 和 Figma 中,我们可以将任何基本形状转换为计算为<path />
的层。在 Sketch 中,我们可以通过选择Layer > Combine > Flatten来完成此操作,而 Figma 我们可以在Object > Flatten Selection ( ⌘ + E下找到此功能在 macOS 上,在 Windows 上为Ctrl + E )。
布尔运算
布尔运算是对形状执行的函数,以几种不同的方式组合它们。 在 Illustrator、Sketch 和 Figma 中,有 4 种标准布尔运算:
- 联盟(联合)
形状的总和 - 减法(减去前面)
底部形状减去形状之间的公共区域 - 相交
形状之间的公共区域 - 差异(排除)
形状的总和减去形状之间的公共区域。
在 Illustrator 中,所有这些功能都会生成一个形状(轮廓)。 这是一个无法撤消的操作——除非使用撤消(在 macOS 上为⌘ + Z ,在 Windows 上为Ctrl + Z )。 另一方面,在 Sketch 和 Figma 中,布尔运算会创建图层组,这些图层组可以在以后取消分组,而不会对内部形状造成任何损害。 但是,您可以将这些组合并为一个形状,以获得与在 Illustrator 中使用上一段中提到的展平功能类似的结果。
问题是,SVG 是否支持布尔运算? 不,它没有。 他们只是合并。 因此,您在 Figma 或 Sketch 中使用布尔运算创建的每个组合形状都将导出为单个<path />
元素。
看起来一样,那么为什么重要?
就如何在 SVG 中定义不同的形状而言,它的语法非常通用。 让我们考虑一个基本的矩形:
这种形状可以在 SVG 中以几种不同的方式定义。 它可以是一个<rect />
元素,一个<polygon />
元素。 它绝对可以是一个<path />
元素(因为一切都可以是一个<path />
元素)。 如果我们决定使用笔触而不是填充来创建它,它也可以是<line />
元素(或<polyline />
元素)。
这些元素中的每一个都呈现一个看起来完全相同的矩形:
长方形 | <rect width="2" height="3" fill="black"/> |
多边形 | <polygon points="0,0 2,0 2,3 0,3" fill="black"/> |
线 | <line x1="1" y1="0" x2="1" y2="3" stroke="black" stroke-width="2"/> |
小路 | 例如<path d="M0,0 l2,0 l0,3 l-2,0" fill="black"/> 或<path d="M1,0 l0,3" stroke="black" stroke-width="2"/> |
但是,如果最终结果(用户代理在浏览器中呈现的图形)看起来相同,那么我们选择哪种方法真的很重要吗? 嗯,确实如此。 根据经验,我总是建议尽可能使用基本形状。
最后但并非最不重要的一点是,在给定的情况下使用最明显的形状。 例如,如果您没有充分的理由,请不要使用直线创建矩形或使用矩形创建圆形。 这背后至少有几个论点:
- 语义/可读性
压缩工具(例如 SVGO)为您提供了计算路径元素的所有基本形状的选项。 它可以为您节省一些时间,但肯定会降低代码的可读性。<path />
语法非常不直观,因此如果您的 SVG 将在代码编辑器而不是设计工具中进行修改,如果您将基本形状保留为基本形状,那么它会更容易理解。 - 文件大小
将形状压缩到路径可能会帮助您缩小文件,但并非总是如此! 例如,圆角矩形作为<path />
比作为<rect />
占用更多空间。 - 动画
您是否尝试过为 SVG 设置动画? 这很有趣——只要你在干净、语义化的 SVG 上进行操作。 使用基本形状,您可以轻松地操作点的半径、宽度、高度或位置等参数。 如果您将形状合并到路径中,大多数这些操作将更难实现或根本不可能。 - 变体/响应性
请记住,SVG 不是 JPG 等静态图像。 您可以对其进行样式设置、主题化、使其具有响应性等等。 与动画一样,保持文件结构良好且语义清晰肯定会帮助您完成任何这些任务。
与每条规则一样,您可以找到一些例外情况。 但是,一般来说,保持 SVG 的可读性、灵活性和结构化是一种很好的做法。
现在,让我们看看其他属性和特性,例如 viewBox、组、变换和视觉效果。
width
、 height
和viewBox
如果您已经对 SVG 有一定的经验,您可能会注意到开始<svg>
标签通常具有以下属性: width
、 height
和viewBox
。 在设计工具中,我们有画板(或 Figma 的框架)的尺寸。 那么这些值究竟是如何相互关联的呢?
让我们从解释我们刚刚提到的<svg>
属性开始。 您可以将viewBox
视为坐标系形式的虚拟画布。 该坐标系的中心位于指定区域的左上角。 <svg viewBox="…">
标签内的所有项目都根据这个坐标系放置并被它剪裁——任何溢出viewBox
的东西都不会被渲染。 viewBox
接受 4 个数字作为其值:
<svg viewBox="0 0 12 8"> … </svg>
由于 SVG 代表Scalable Vector Graphics,因此这些数字不需要单位。 把它想象成一个可以放大和缩小到任意大小的抽象坐标系。 不要太担心前两个数字,很可能你不需要它们。 后两者通常很重要。 这些是我们的 SVG 画布的实际尺寸。
viewBox
不能确定 SVG 的大小。 它只是指定了绘制 SVG 的区域的坐标。 因此,当在 web 上使用时,带有指定viewBox
的<svg>
将始终占用所有可用空间并保留viewBox
设置的比例——除非我们用 CSS 阻止这种情况或设置width
和/或height
属性。
width
和height
是设置 SVG 元素的实际宽度和高度的<svg>
属性。 与viewBox
相反,它们应该使用指定的单位,例如像素、ems 或 rems。 这意味着我们也可以用它们转换height
width
viewBox
width
height
viewBox
的图形:
现在,当我们从设计工具导出 SVG 时会发生什么? 在 Sketch 和 Figma 中,所有资源(无论它们是单层、组还是画板)总是会得到一个等于导出元素的尺寸和以像素为单位设置的width
和height
的viewBox
,等于最后两个值viewBox
。 在 Illustrator 中,所有资源都有一个viewBox
,指定方式与 Sketch 和 Figma 中相同,但没有应用width
和height
。
团体
组是在设计工具中组织层的基本手段。 除了设置层次结构外,组还用于将批量操作(例如转换)应用于多个元素。 群组在 Illustrator、Sketch 和 Figma 中的工作方式没有显着差异,幸运的是,SVG 群组 ( <g>…</g>
) 的基本功能几乎相同。
变换
在 SVG 中,我们可以对元素应用五种基本变换:
-
translate
:沿垂直和/或水平轴移动元素; -
scale
:沿垂直和/或水平轴缩放元素: -
rotate
:围绕给定点以度数指定的给定角度创建二维旋转; -
skew
(skewX
或skewY
):沿垂直或水平轴以度数指定的给定角度倾斜元素; -
matrix
:最复杂和最通用的可用变换函数。 由于解释矩阵变换的工作原理需要大量的代数讨论,因此它远远超出了本文的范围。 让我们承认matrix
允许您执行许多复杂的变换,例如拉伸、挤压、剪切等。
注意:请注意,尽管某些 SVG 变换看起来与 CSS 变换非常相似,但它们并不相同。 例如,CSS 提供 2D 和 3D 旋转功能,而 SVG 只有一个 2D 旋转功能。 此外,虽然 CSS 接受各种角度单位,例如度或弧度,但 SVG 旋转始终以度为单位设置,因此可以省略单位(例如rotate(45)
, NOT ~~rotate(45deg)~~
)。
所有这些变换都可以应用于任何 SVG 元素,例如形状或组,并且是非破坏性的,即不会影响元素的原始几何形状。 我们通过一个transform
属性应用变换:
<g transform="scale(3) rotate(90) translate(50,100)"> … </g>
现在让我们来看看设计工具吧! 因此,我们在设计工具中应用的大多数变换都直接与对象的几何形状及其在画布上的位置交互。 它们不独立于形状,也不会作为 SVG 变换函数导出。
旋转在这里是个例外,它们的值与元素的几何图形分开存储在检查器中,并且它们确实导出为transform="rotate(…)"
函数。
有趣的是,同样的规则适用于 Sketch 和 Figma 中的翻转(反射)(不在 Illustrator 中!)。 不过,他们每个人都有自己的方法。 Sketch 使用负缩放和平移的组合来实现翻转效果,而 Figma 在单个矩阵函数中执行翻转。
边界半径
我们已经谈到了圆角矩形,但是如何将其他形状弄圆呢? 事实上,在我们讨论的所有设计工具中,您可以将任何形状的角弄圆,而不仅仅是矩形。
但是 SVG 呢? <polygon />
和<path />
元素也有rx
和ry
属性吗? 很不幸的是,不行。 矩形以外的任何形状,一旦你将它的任何角弄圆,将始终作为<path />
元素导出,将圆角视为形状几何图形的一个组成部分。
填充和描边
Illustrator、Sketch 和 Figma 都支持填充和描边作为任何形状的基本属性,SVG 中也是如此。 因此,在设计工具中指定的填充在fill
属性中导出,而描边在stroke
属性中导出。 不要认为这一切都那么简单。 细节决定成败。
颜色填充
颜色填充是最基本的可用填充,并指定为单一纯色(例如#3fd8e2
)。 在 SVG 中,该值直接放在fill
属性中(例如fill="#3fd8e2"
)。
设计工具使用十六进制值(例如#0000ff
)导出颜色填充,尽管在 SVG 中,您也可以使用 CSS 已知的所有其他命名方案,例如颜色名称(例如blue
)、RGB 值(例如rgb(0,0,255)
) 甚至 HSL 值(例如hsl(240,100%,50%)
)。
填充不透明度
当涉及到填充不透明度时,SVG 接受半透明颜色(例如 RGBA 值),尽管它也提供了一个fill-opacity
属性。 由于兼容性问题,推荐使用fill-opacity
的方法,它也是 Figma 和 Sketch 使用的方法。 (我在这里没有提到 Illustrator,因为 Illustrator 不允许您控制填充不透明度。)因此,如果您想创建一个填充有半透明红色的 SVG 正方形,您可以执行以下操作:
<rect width="100" height="100" fill="rgba(255,0,0,0.5)" />
但更推荐的方法(由 Sketch 和 Figma 使用)是:
<rect width="100" height="100" fill="#ff0000" fill-opacity="0.5" />
渐变填充
如果您熟悉 CSS,您可能知道在背景方面,颜色和渐变背景之间的切换相对简单。 在这两种情况下都可以使用相同的background-color
(或background
)属性。 由于 SVG 中的渐变比 CSS 渐变更古老,它们的语法也大不相同。
要使用渐变是 SVG,您首先需要在<defs>…</defs>
标记中定义它,然后在fill
属性中引用它,例如:
<defs> <linearGradient> <stop stop-color="red" offset="0%"></stop> <stop stop-color="blue" offset="100%"></stop> </linearGradient> </defs> <rect fill="url(#myGradient)" />
因此,当您使用渐变填充时,在 SVG 导出期间发生的情况是渐变被添加到<defs>
并且在下面的代码中被引用。
要记住的重要一点是 SVG 仅支持线性和径向渐变。 角度渐变或渐变网格等效果不会导出到 SVG。
图案/图像填充
Sketch 和 Figma 还提供图像填充,其中光栅图形用于填充整个元素或作为重复图案。
在将图像填充导出到 SVG 时,它实际上与渐变非常相似。 图像在<defs>
中使用<pattern>…</pattern>
元素定义,然后在fill
属性中引用:
<defs> <pattern patternUnits="objectBoundingBox"> <use xlink:href="#picture"></use> </pattern> </defs> <rect fill="url(#myPattern)" />
要使其工作,必须在某处定义引用的#picture
图像。 设计工具会将它们作为<image/>
元素直接嵌入到 SVG 中,尽管在性能方面不推荐使用这种方法。 如果您确实需要在 SVG 中使用光栅图像,我建议您从 SVG 中删除图像标签,并将其用作独立文件:
<defs> <pattern patternUnits="objectBoundingBox"> <use xlink:href="#picture"></use> </pattern> <image xlink:href="image.png"/> </defs> <rect fill="url(#myPattern)" />
笔画
SVG 中的stroke
属性,与fill
属性相同,接受各种格式的颜色,例如 hex、RGB 或 HSL。 与fill
类似,您可以使用stroke-opacity
控制描边的不透明度。 此外,与fill
相同,笔画可以使用渐变作为其值。 所有这些效果都可以在设计工具中实现并成功导出到 SVG。
中风帽和连接
不过,也有一些特定于笔划的属性。 首先,您可以控制笔画宽度。 设计工具支持它并将其导出为stroke-width
属性。 您还可以控制笔画的结束和连接。 SVG 允许您通过stroke-linecap
和stroke-linejoin
属性来定义它们。 有三种可能的端盖: butt
端盖、 round
端盖和square
端盖,以及三种可能的连接: miter
连接、 round
连接和bevel
连接。 Caps 和 Joins 都可以在 Illustrator、Figma 和 Sketch 中控制,并且可用的 caps 和 joins 与 SVG 中可用的相匹配。
虚线和虚线笔画
我们可以用笔划实现的另一个效果是虚线笔划。 在 Illustrator 和 Figma 中,您可以设置多个虚线和间隙,而在 Sketch 中,只能设置单个虚线和间隙序列。
SVG 允许您使用stroke-dasharray
属性创建虚线。 stroke-dasharray
允许将一系列多个破折号和间隙作为其值传递,该值与 Figma 和 Illustrator 的功能相匹配。 这也意味着 Sketch 不允许您在这种情况下使用 SVG 的全部可能性。
一个有趣的边缘案例是虚线。 我们通过将stroke-linecap
设置为round
并将破折号的长度设置为零来实现它,例如:
<line … stroke="black" stroke-dasharray="0 2" stroke-linecap="round"/>
注意:目前,Figma 用户遇到了一个不允许他们创建虚线的错误。 例如,使用0, 10
或10, 0
作为破折号的解释方式与10, 10
相同,并给出常规的虚线而不是虚线。 幸运的是,有一种方法可以绕过它。 与其使用零,不如使用一个非常小的值,例如0.0001, 10
这应该会产生完美的虚线,正如预期的那样。
笔画对齐
设计工具和 SVG 之间还有另一个更显着的区别:笔画对齐。 Illustrator、Sketch 和 Figma 都允许您控制笔画的对齐方式,并将其设置为内部、外部或居中对齐。 但猜猜怎么了? SVG 1.1 不支持笔画对齐。 在 SVG 中,所有笔划都是居中对齐的笔划。 没有内笔画或外笔画。 这就是为什么当您将外部和内部对齐的笔画导出到 SVG 时会发生一些非常奇怪的事情的原因。
在这种情况下,Illustrator 会将形状及其笔划导出为两个单独的形状。 因此,如果您在 Illustrator 中将内部笔划或外部笔划应用于矩形,则在 SVG 中,它将生成一个矩形和一个单独的<path />
元素表示矩形的笔划,例如:
<rect x="10" y="10" width="120" height="120"/> <path d="M120,20V120H20V20H120M140,0H0V140H140V0Z"/>
这种行为有一些非常重要的影响。 例如,您不能再更改笔划的宽度或使其变为虚线。 它也不会像“真实”笔画那样缩放。 更重要的是,Illustrator 会更改原始形状的尺寸,例如,一个 100×100 的正方形和一个 20 单位的粗体内部笔划实际上会导出为 120×120 的正方形,以避免渲染问题。 最终,这不是中风。 它只是另一种带有填充的形状。
Figma 和 Sketch 有不同的方法。 它们忠实地将所有笔划导出为笔划,但它们会重新计算形状的尺寸。 因此,如果您有一个半径等于 5 且内部笔划等于 2 的圆,那么您将在 SVG 中找到一个半径等于 4 的圆(并且笔划仍然等于 2)。
这种方法允许 Figma 和 Sketch 避免 Illustrator 中提到的大多数问题。 然而,对于一些更复杂的形状,这种技术可能会变得不精确,最终结果与预期的有点不同。 这就是为什么 Sketch 和 Figma 的方法不一定更好的原因——它肯定更具语义、性能和灵活性,但 Illustrator 的解决方案更准确。
注意:笔画对齐的相同问题也适用于 CSS。 CSS border
属性也不支持内部或外部对齐。 但是,如果您愿意,您可以使用outline
和box-shadow
属性来破解此行为。
多个填充和描边
在设计工具中,您可以为每层添加多个填充和描边。 一旦结合不透明度和混合模式等属性,这很有意义。 不幸的是,SVG 不支持这样的功能。 如果您导出具有填充和/或描边的图层,它将成倍增加,并且每个描边和填充将应用于其自己的图层。
阴影、滤镜和其他效果
现在让我们谈谈一些不太受欢迎的效果。 SVG 是一种非常强大的语言,实际上比它通常在网络上使用的方式要强大得多。 SVG 最有趣的功能之一是广泛的高级视觉效果,称为 SVG 滤镜。
SVG 过滤器的全部可能性范围太广,无法在本文中描述。 如果您想了解更多关于它们的信息,我强烈建议您查看 Sarah Soueidan 关于此主题的一些演讲和文章。
过滤器,与图案或渐变相同,需要定义以稍后将它们应用于图层。 每个过滤器都被定义为一个<filter>…</filter>
元素,可以包含许多效果,称为过滤器原语,每个都代表一个单独的视觉效果。
过滤器基元可以组合在一起以创建过滤器。 例如,这是应用于矩形的基本模糊效果如下所示:
<defs> <filter> <feGaussianBlur stdDeviation="10"/> </filter> </defs> <rect filter="url(#GaussianBlur)" width="200" height="300"/>
…but you can also create a more complex filter that consists of more than one filter primitive:
<defs> <filter> <feGaussianBlur stdDeviation="10"/> <feMorphology operator="dilate" in="SourceGraphic" radius="3" /> </filter> </defs> <rect filter="url(#GaussianBlur)" width="200" height="300"/>
Out of the three design tools we discuss, only Illustrator lets you play with SVG filters. You can find them in the app's menu, under Effect > SVG Filters . Sketch and Figma are a completely different story. Any effects these applications offer are mostly focused on CSS and native implementations, eg Background Blur effect was implemented primarily for designing iOS apps and Drop/Inner Shadow effects parameters are matching CSS properties ( box-shadow
and text-shadow
).
It doesn't mean we can't export these effects to SVG. 我们可以。 However, translating these effects to SVG is utterly not as straightforward as to CSS. Let's consider a square with a drop shadow applied.
This is how our square could look like, once exported to HTML/CSS:
<style> .square { width: 100px; height: 100px; background: red; box-shadow: 10px 10px 24px 0 rgba(0,0,0,0.5); } </style> <div class="square"></div>
A similar square exported from Sketch to SVG gives us a significantly more complex piece of code:
<defs> <rect x="14" y="14" width="100" height="100"></rect> <filter x="-31.0%" y="-31.0%" width="182.0%" height="182.0%" filterUnits="objectBoundingBox"> <feOffset dx="10" dy="10" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset> <feGaussianBlur stdDeviation="12" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur> <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix> </filter> </defs> <g> <use fill="black" filter="url(#filter-2)" xlink:href="#square"></use> <use fill="#FF0000" fill-rule="evenodd" xlink:href="#square"></use> </g>
What happens here is that Sketch duplicates the square, so we have two identical squares, one above another, and turns the duplicate into a shadow.
To accomplish this, it applies a filter to a duplicated square that consists of three different filter primitives:
- one to offset the square;
- one to set its color to semi-transparent black;
- one to blur it.
In other design tools, we would encounter a similar situation.
It doesn't mean that we should never, by all means, use shadows in SVG. It's handy to keep in mind though that as long as SVG gives you a very powerful toolkit to modify your graphics, some seemingly simple effects are not that simple to achieve at all.
混合模式
混合模式(例如Darken 、 Multiply或Overlay )允许通过以不同方式组合它们的值来混合两个或多个元素。 平面设计师(以及 Adobe Photoshop 等应用程序)众所周知,混合模式也适用于 Sketch、Figma 和 Illustrator。
在 SVG 中,混合模式作为过滤器之一存在。 他们有自己的<feBlend />
过滤器原语。 然而,由于<feBlend />
的语法相当复杂,Sketch、Figma 和 Illustrator 使用 CSS 代替:
.rectangle { mix-blend-mode: overlay; }
现在mix-blend-mode
浏览器支持相当不错,这应该不是一个大问题。 但是,如果确保包括 Microsoft Edge 和 IE 在内的防弹浏览器支持对您很重要,您将不得不手动将 CSS 混合模式替换为 SVG 过滤器。
与多个填充和描边一样,SVG 不支持直接应用于填充和描边属性(而不是整个图层)的混合模式。 如果您尝试使用自己的混合模式将填充和描边从设计工具导出到 SVG,则图层将成倍增加,并且混合模式将应用于图层的各个副本。
符号和组件
在上面的一些代码示例中,您可能已经注意到我们尚未讨论的元素: <use>…</use>
元素。 <use>
让我们在 SVG 中定义和重用元素,有点类似于 Illustrator 中的 Symbols 和 Figma 中的 Sketch 或 Components。 还记得在<defs>…</defs>
标记中定义模式、渐变和过滤器,以便它们可以在 SVG 代码的其他部分中使用吗? 事实上,任何 SVG 元素都可以通过这种方式定义和重用。 一旦定义了形状或组,您可以在文档的其余部分多次引用它,例如:
<defs> <circle cx="100" cy="100" r="20"/> </defs> <use fill="red" xlink:href="#circle"> </use> <use fill="green" xlink:href="#circle"> </use> <use fill="blue" xlink:href="#circle"> </use> …
您还可以使用<symbol>…</symbol>
标签重用更复杂的结构。 Symbol 在我们的 SVG 中充当一个单独的主体,并且可以拥有自己的viewBox
属性(参见 Width、height 和 viewBox 以供参考)。
这是否意味着我们的设计工具的符号和组件将被导出为 SVG 符号? 在 Illustrator 中——是的,确实如此。 在 Sketch 和 Figma 中——不,它没有。 为什么? 首先,因为 Illustrator 符号相当简单,可以轻松转换为 SVG,而 Sketch 的符号和 Figma 的组件根本没有那么简单,并且导出它的一些功能(例如嵌套覆盖)将非常棘手甚至不可能。
文本
如果我们不提及排版,它就不是一个全面的指南。 所有设计工具都提供了与文本相关的各种工具。 SVG,即使通常用于图形,也支持文本元素。
Illustrator、Sketch 和 Figma 都支持将文本导出为 SVG,并将文本层计算为 SVG 中的<text>…</text>
元素。 SVG 文本元素像任何其他图形元素、形状等一样呈现,唯一的区别是它们是文本。
与 CSS 一样,我们可以控制所有基本文本的参数,例如粗细、行高或对齐方式。 事实上,如果您知道如何在 CSS 中设置文本样式,那么您就已经知道如何在 SVG 中进行设置了。 但是,它可能会感觉有点老派。 首先,所有参数都必须设置在内联属性中,类似于 HTML 3.2 的黄金标准。 其次,没有速记。 例如,您不会找到任何类似于font
CSS 属性的东西。 这是因为 SVG 文本属性实际上是基于 CSS 2 规范,它把我们带回到了 90 年代,并且比我们今天所知道的 CSS 更古老。
尽管如此,每当我们希望某些文本层成为 SVG 代码时,所有这些属性都可以从设计工具中完美导出。
自定义字体
不幸的是,当涉及到自定义字体时,事情变得有点棘手。 回到过去,当 SVG 1 标准被创建时,自定义字体对于 Web 来说并不常见。 每个人都使用标准字体,例如 Tahoma、Verdana 或 Courier。 花哨并使用人们默认情况下在他们的机器上没有的字体,通常意味着无情地将它们光栅化并将它们用作图像。 但是,SVG 实现了自己的字体格式,称为 SVG 字体。 今天,在 SVG 1.0 发布 18 年后,大多数主流浏览器不再支持 SVG 字体。
幸运的是,SVG 与 CSS 配合得非常好,这意味着我们可以使用 Web 字体代替 SVG 字体,例如:
<style> @import url("https://fonts.googleapis.com/css?family=Roboto"); </style> <text x="20" y="50" font-family="Roboto">Text</text>
除了一个重要的注意事项外,让我不要在这里详细介绍实现网络字体:不要忘记它。 换句话说,如果您在 SVG 中使用自定义字体,您需要记住将这些字体提供给客户端,就像在 HTML/CSS 中一样。
大纲字体
有人可能会争辩说,比争论字体和所有内容更容易的是勾勒出所有的文本层,以后再也不用担心它们了。 尽管如此,至少有几个很好的理由不将文本更改为形状:
- 您不能在导出之前或之后编辑轮廓文本。
使用轮廓文本时,您需要记住始终在 Illustrator、Sketch 或 Figma 文件中保留可编辑的副本。 否则,一旦它们被勾勒出来,您将无法编辑文本图层。 这给流程增加了不必要的复杂性。 更不用说在 SVG 导出后编辑概述的文本了。 SVG 中的文本可以随时更新。 每次您想要进行最小的副本更改时,大纲文本都需要打开源文件。 - 大纲文本不可访问。
SVG 中的文本与 Web 上的其他文本元素一样,可以由屏幕阅读器和其他可访问的技术读取。 通过概述文本层,您可以防止人们使用此类技术访问您的内容。 - 人们期望 text 是 text 。
大多数使用网络的人对 SVG、HTML 或设计工具一无所知。 如果他们看到文字,他们希望它只是那样。 他们可能想要选择、复制或放入搜索引擎。 所有这一切都可以通过 SVG 中的文本实现 — 除非您对其进行概述。 - 不要忘记搜索引擎优化。
SVG 中的文本也可以被搜索引擎访问和使用。 通过概述文本,您可以使您的内容不那么容易被搜索到,并且可能不那么被公众看到。
概括
非常感谢您与我一起了解使用 SVG 和设计工具的来龙去脉。 本文绝对没有涵盖该主题的全部范围,尽管它应该足以处理最常见的用例。 如果您对此处未提及的内容有任何疑问或疑问,请随时在评论中发表!