0%

通过SVG文件制图

SVG 介绍

以下信息摘自 维基百科

可缩放矢量图形(英语:Scalable Vector Graphics,缩写:SVG)是一种基于可扩展标记语言(XML),用于描述二维矢量图形的图形格式。SVG由W3C制定,是一个开放标准。

SVG允许3种图形对象类型:矢量图形、栅格图像以及文本。图形对象(包括PNG、JPEG这些栅格图像)能够被编组、设计、转换及集成进先前的渲染对象中。文本可以在任何适用于应用程序的XML名字空间之内,从而提高SVG图形的搜索能力和无障碍性。SVG提供的功能集涵盖了嵌套转换、裁剪路径、Alpha通道、滤镜效果、模板对象以及可扩展性。SVG严格遵从XML语法,并用文本格式的描述性语言来描述图像内容,因此是一种和图像分辨率无关的矢量图形格式。

SVG参考资料:W3C SVG 官方标准网站W3school上关于SVG的教程

制图能力

以下是一个SVG样例,在这个SVG文件中(图片是预览效果),列出了SVG支持的三种内容类型:图片、文本、矢量图。

svg-image-1.png

那么,我们如何利用一个现有svg文件去产出一张图呢?正同如下流程图阐述一样,由设计师事先设计好模版,然后在制图时将需要变动的内容进行替换,最终转换产出所需格式(如 PNG/JPG)的图片文件。在整个过程中,可以去对变更元素进行加工处理,也可以对最终的产出物进行加工处理。而在元素方面,在实际使用中往往只会涉及到图片和文本信息的变更,其他的信息以及相关样式由设计师设定好即可。

svg-image-5.png

图片元素

对于图片元素标签,实际使用中往往只会关注到 宽(width)、高(height)、图片信息(xlink:href)等三个属性,图片的其他属性(比如坐标x/y)在无特殊要求下是不需要进行变动的。如下是一个简略的图片标签(<image></image>)结构:

1
<image id="img" x="18" y="14.625" width="132" height="99" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAAJYCA</image>

实际操作中,一般只需要操作图片信息(xlink:href)属性即可,如替换一张新图片的地址,该属性值支持图片的URL和二进制流的Base64编码字符串。 宽(width)、高(height)属性控制了区域的矩形大小,在替换新的图片时,无论图片的尺寸是多少都会自动等比缩放到最长边符合要求并居中放置在矩形区域内,这是SVG文件自身的能力。

文本元素

相比于图片元素标签,文本元素标签的关注点要复杂的多,也是处理最复杂的。如坐标(x/y)、字体大小(font-size)、字体(font-family)等属性,以及文本标签(<text></text>)的内容及其子标签tspan。如下是一个简略的文本标签(<text></text>)结构:

1
2
3
4
5
<text id="我是文本,我膨胀了!GO GO" font-family="PingFangSC-Regular, PingFang SC" font-size="22" font-weight="normal" fill="#000000">
<tspan x="199" y="107">我是文本,我膨胀了!GO GO</tspan>
<tspan x="199" y="137">我换行了哟,你要注意啦,再</tspan>
<tspan x="199" y="167">换一行...</tspan>
</text>

在文本的合成处理方面,虽然只是放置(替换)一个文本,但整体上会涉及到方方面面的效果,如下所示,接下来我们会详细阐述这几个方面。

  • 文本的字体是否符合预期(预定字体或者动态设置的字体)
  • 文本的对齐布局方式是否符合预期(如果有设定对齐方式)
  • 文本的是否会换行以及换行效果是否符合预期(同文本的长度与区域的长度相关)

字体支持

字体方面,因为最终会以SVG为基础来产出图片,故需要我们制图能力的系统服务器上对相关的字体要进行支持,否则是达不到字体效果要求的。而详观SVG文件源内容,文本字体名的呈现多种多样,以本文的 “PingFangSC-Regular, PingFang SC” 字体为例,中文名为“平方简-常规”字体,但不同的软件导出的SVG呈现不同,比如“PingFangSC-Regular”、“PingFangSC Regular”,故对字体的维护以及对svg制作软件的统一尤为重要。

对齐方式

对齐方式在实际文字效果中分为水平对齐和垂直对齐,而文本的对齐方式使用较多的是水平对齐,这里着重阐述一下水平对齐的实现方案。

就SVG的自身特性来讲,是没有水平对齐(左/中/右对齐)的效果的。SVG是一种矢量图,其支持的对齐方式为 start、middle、end三种,如下所示,为了体现效果在图形上画了一个矩形框。

  • 原始文件效果(无设置,默认参照点为起始坐标点)
    svg-image-2.png

  • SVG的start/middle/end效果
    svg-image-3.png

  • 期望效果:左/中/右对齐
    svg-image-4.png

所以如果想要实现效果,需要重新计算文本的坐标,即文本该放置在指定区域的什么位置。假设区域的长度(即矩形横向宽)为length,SVG源文件的改动设定如下:

  • 居左对齐 text-anchor=”start”, transform=”translate(0, 0)”
  • 居中对齐 text-anchor=”middle”, transform=”translate(length/2, 0)”
  • 居右对齐 text-anchor=”end”, transform=”translate(length, 0)”

这里 transform=”translate(x, y)” 代表文本在当前坐标的基础上 x/y 坐标的偏移量,区域的长度 length 可以使用dom操作的函数得到:

  • getComputedTextLength 可直接得到length
  • getBBox 可得到矩形区域的宽高 {x: -251.859375, y: 543.5, width: 570.859375, height: 31}

文本换行

文本换行的效果实现依赖于 tspan 标签,首先需要定义文本框区域的宽度,在文本填充超过宽度时新增一个 tspan标签来继续填充文本,直到填充完成为止,当然是在忽略文本框高度限制的情况下;在换行是的行间距(换行y坐标偏移)方面亦是需要设计师给定的;而SVG是矢量图,是没有所谓文本区域宽高限制的,所以得对源文件预处理来打上自定义的属性信息(行间距、区域长度等)。

行间距的设置准则可参考 设计时sketch中字体行高到底该如何设置

制作加工

如前面所说,在制作图时可加工的阶段可分为对元素的加工和对产出结果图加工,这些都是抛开SVG文件之外的人为能力,比如对图片的美化、采集等处理,对文本的优化处理。

模型表达

在对SVG文件及其制图能力有所了解后,那么如何用模型来表达和管理SVG模版文件呢?

如果以矢量图的角度来说,可以直接抽象为文本和图片模型,而模型的属性即为矢量图标签的属性信息,该种方式特点是非常直观,但是缺点也很明显,即属性多的原因为模型带来了复杂性,以及扩展性限制。

当然还有一种更友好的表达方式,即把制图的过程比喻为拼图游戏,SVG文件就是我们拼图的一个模版;拼图游戏是将打乱的所有模块最终拼成一个整图,而SVG就像是一个预先拼上了一些模块(固定无需改变的部分),玩家只需要将空出来的部分填充上自己的想要设定的内容。在这种思维理解框架下,可以将SVG的文本和图片标签抽象为坑位(模块/槽位),我们要做的就是填坑。此思维框架下的模型表达如下所示:

字段 示意 阐述
ID 模版内坑位唯一ID 对应文件内标签的ID
类型 图片/文本 对应图片/文本标签
名称 坑位标识
描述
坑位内容信息 图片链接/文本内容
约束 坑位的约束信息 标签的属性信息表达,类型不同约束不同,如图片的宽高、文本的字体/对齐方式等等
是否可变更 是否可以替换

技术支撑

SVG是在W3C标准下的,其本身亦是XML扩展文件,所以自身可以用dom的常规操作来操控解析文件内容和替换文件内容。但要想更友好的操控还是的使用专业的操作工具batik家族,针对SVG文件的内容操控和产出图片,主要使用到如下工具包:

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-svg-dom</artifactId>
<version>${batik-svg-dom.version}</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-transcoder</artifactId>
<version>${batik-transcoder}</version>
</dependency>