臃肿的 SVG:The Good, the Bad and the Ugly

SVG: The Good, the Bad and the Ugly

原文链接:www.eisfunke.com/posts/2021/...

原文作者:Nicolas Lenz

译者:菜小鸟魔王

SVG[1],也就是我们常说的 scalable vector graphics(可缩放矢量图形)的缩写,是一种特别设计来存储矢量图像的格式,这些图像可以随意放大缩小而不会失真。这篇文章,我会详细阐述我对SVG的看法,指出它的不足之处,并给出我认为能够提升SVG表现的改进方案。

我已经使用SVG和Inkscape好几年了,经常用它们来绘制草图(sketches)和制作图形(graphics),还喜欢动手编写代码实现SVG内容,这让我既能追求图像绘制的精确性,又能通过编程展现我对代码艺术的热爱。我跟SVG有一种爱恨交织的关系。它确实功能强大,也有一些不错的免费开源工具,但它的格式,坦白说,真的不怎么好看。

The Good

  • 无论是在Adobe Illustrator这样的专业软件中,还是在Inkscape这类免费工具里,甚至是各大浏览器中,SVG格式都能得到很好的支持。
  • 网页标准支持SVG这种数据格式,SVG可以直接嵌入到网页中,而且还能和CSS实现一些"骚操作"。
  • 这种数据格式基于XML,所以SVG的语法让人倍感亲切,具有极强的可扩展性,可以融入XML生态。比如,借助XLink[2],可以轻松地在SVG文件中引用其他elements(译者注:常见的SVG元素包括:<circle><ellipse><rect>等)或definitions(译者注:在SVG中,<defs> 元素用于定义一系列可以被文档其他部分引用的对象。比如渐变 (<linearGradient>, <radialGradient>)、模式 (<pattern>)、符号 (<symbol>)等。);而Inkscape[3]则通过自定义的XML标签,让SVG成为了编辑器间进行数据交换的"桥梁"。
  • SVG的功能非常强大,可以用它来做很多事情。这种数据格式不仅支持各种 path types 和shapes(译者注:path types and shapes,路径(<path> 元素)是SVG中最灵活的图形元素,可以绘制几乎任何类型的形状。路径由一系列指令组成,这些指令可以是直线、曲线、弧线等。路径指令的字母(大写或小写)和数值组合在一起形成路径数据字符串。形状(如 <circle><ellipse><rect><line><polyline><polygon>)则是预定义的路径类型,它们提供了绘制常见几何形状的快捷方式。这些形状可以单独使用,也可以组合起来创建更复杂的图形。),还支持文本等功能,更厉害的是,它还能实现动画、渐变、特效等复杂效果。

The Bad

这是网络世界的一种标准数据格式,而如同其他网络标准一样,SVG极其臃肿。SVG 的规范[4]长达 826 页,其内容之繁复令人咋舌。不仅如此,由于它基于 XML 并与其他网络标准相互连接融合,使得 SVG 的应用范围变得极其广泛,复杂程度令人目眩。

若想要确保所有的 SVG 文件都能正确渲染,除了要啃下 800 多页的 SVG 规范外,还得额外钻研 20 页的 XLink 规范[5]。对了,别忘了还有 CSS。而且 SVG 还支持 JAVASCRIPT,没错,SVG 文件中可以嵌入 <script> 标签[6]

SVG 与网络浏览器简直是天作之合。浏览器们本身就臃肿不堪,早已实现了 CSS 和 JavaScript 等相关功能,而这些技能正是实现完整的 SVG 功能所必需的。SVG 的问题,归根结底,也是整个网络世界存在的问题[7]。其应用范围广泛,臃肿且难以使用。

想要在一天、一周甚至一个月内掌握 SVG?这几乎是不可能完成的任务。往往只是实现部分功能,让人难以一窥全貌,也让用户在追求 SVG 文件的跨平台兼容性时,对到底可以使用哪些功能感到迷茫。

再者,SVG 的 XML 基础语法既不美观也不精炼。无论是人工编写还是算法解析和自动化生成,都让人倍感疲惫。

The Ugly

从上述提到的问题中,我们可以聚焦到一个关键点,这正是我在探讨机器语言与人类语言设计差异的文章中[8]所深入剖析的:SVG 在其定位上模糊不清,它试图同时迎合机器和人类的需求,然而在两者之间却未能找到平衡点,反而在两个领域都显得力不从心(甚至可以说都很糟糕!)。

SVG 是否能够高效地被机器处理?显然不是,它太臃肿了。开发专门用于解析、渲染和生成 SVG 文件的软件工具,是一项耗时费力的工作。SVG 的语法结构繁复冗长,许多高级功能其实可以通过更基础的元素组合来替代。

那么,SVG 这种格式适合人类直接使用吗?答案依然是否定的。一方面,其复杂的语法结构也不利于人类用户使用;另一方面,它又缺乏一些直接操作时所需的实用功能。如果要寻找一种专为人类设计的图形描述语言,LaTeX 的 TikZ[9] 或许是个学习榜样。尽管在我看来,TikZ 在用户体验等方面还有待提升,但它确确实实是为人而设计的,具备了一系列辅助绘制复杂图形的必备功能。然而,没有人会将 TikZ 代码视作成品图形的交换标准,毕竟没有人愿意去阅读长达 1300 页的产品手册只是为了浏览一张图像。相反,人们会选择将其编译成 PDF 格式(虽然 PDF 本身也存在诸多问题,如格式臃肿等)。如果 SVG 真正致力于为人类用户服务,那么将其转化为机器可读的格式应该是其发展方向,可惜,SVG 并没有做到这一点。它既非纯粹面向机器,也非完全为人类而设,可以说,SVG 陷入"两头不讨好"的尴尬境地。

那么接下来该怎么办呢?

一个明智的选择是设计一种简易的矢量图形交换格式,使机器能够轻松处理。这种格式应尽可能简化功能。也许可以基于JSON,但绝不能基于XML。理想情况下,应该能在几天之内,甚至更快,几小时内,无需借助庞大的XML生态系统库就能实现一个基础的渲染器。贝塞尔曲线(Bezier curves)、椭圆曲线(elliptic curves)、填充(fills)、轮廓(outlines)和渐变(gradients)等基本元素,足以覆盖所有静态SVG的渲染需求。此外,可以考虑通过扩展支持,在独立的文件格式中加入动画效果的矢量图形交换格式,让机器处理变得更简单。

这种精简且边界清晰的格式,应当配备一套严格的标准测试套件,使得能够相对轻松地在浏览器和图像查看软件中集成。用户将能够确信自己的图形作品在各种平台上的表现一致,开发者也不必再为XLink、CSS和JavaScript的兼容性问题头疼。这一方案有望减少数据传输量,降低计算资源消耗。为了确保与SVG的兼容性,可以开发相应的转换编译工具。

这种格式可能成为像 Inkscape 和 Adobe Illustrator 这样面向用户的程序的导出格式。对于喜欢通过编程方式来处理图形的人来说,已有诸如 TikZ、Haskell diagrams[10] 或 Python matplotlib[11] 等工具,它们同样也可以支持导出至新提出的极简交换格式。

我正构想一种以机器为中心的精简向量图形格式 ------------ 有人提议命名为"SlimSVG"(这个名字挺逗的~),并计划开发一套以人类为中心的 Haskell 图形生成库,其目标与前者类似 ------------ 服务于我的个人需求,或许这将成为我在大学的一个科研项目。

简而言之:明确一门语言的定位是服务于人类还是机器,然后聚焦于做好其中一个方向。专注于把一件事情做到极致,而非尝试兼顾却两头不讨好。

文中链接

1\] [en.wikipedia.org/wiki/Scalab...](https://link.juejin.cn?target=https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FScalable_Vector_Graphics "https://en.wikipedia.org/wiki/Scalable_Vector_Graphics") \[2\] [en.wikipedia.org/wiki/XLink](https://link.juejin.cn?target=https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FXLink "https://en.wikipedia.org/wiki/XLink") \[3\] [inkscape.org/](https://link.juejin.cn?target=https%3A%2F%2Finkscape.org%2F "https://inkscape.org/") \[4\] [www.w3.org/TR/SVG11/RE...](https://link.juejin.cn?target=https%3A%2F%2Fwww.w3.org%2FTR%2FSVG11%2FREC-SVG11-20110816.pdf "https://www.w3.org/TR/SVG11/REC-SVG11-20110816.pdf") \[5\] [www.w3.org/TR/xlink11/](https://link.juejin.cn?target=https%3A%2F%2Fwww.w3.org%2FTR%2Fxlink11%2F "https://www.w3.org/TR/xlink11/") \[6\] [developer.mozilla.org/en-US/docs/...](https://link.juejin.cn?target=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FWeb%2FSVG%2FElement%2Fscript "https://developer.mozilla.org/en-US/docs/Web/SVG/Element/script") \[7\] [drewdevault.com/2020/03/18/...](https://link.juejin.cn?target=https%3A%2F%2Fdrewdevault.com%2F2020%2F03%2F18%2FReckless-limitless-scope.html "https://drewdevault.com/2020/03/18/Reckless-limitless-scope.html") \[8\] [www.eisfunke.com/posts/2021/...](https://link.juejin.cn?target=https%3A%2F%2Fwww.eisfunke.com%2Fposts%2F2021%2Flanguage-design-machine-or-human.html "https://www.eisfunke.com/posts/2021/language-design-machine-or-human.html") \[9\] [texdoc.net/pkg/tikz](https://link.juejin.cn?target=http%3A%2F%2Ftexdoc.net%2Fpkg%2Ftikz "http://texdoc.net/pkg/tikz") \[10\] [diagrams.github.io/](https://link.juejin.cn?target=https%3A%2F%2Fdiagrams.github.io%2F "https://diagrams.github.io/") \[11\] [matplotlib.org/stable/inde...](https://link.juejin.cn?target=https%3A%2F%2Fmatplotlib.org%2Fstable%2Findex.html "https://matplotlib.org/stable/index.html") > 原文作者介绍: > > **Hi!** I'm Nicolas. I'm a computer science student in Germany. My main interests are functional programming, type systems, free software and infrastructure -- both in computing and in cities. email: [www.eisfunke.com/res/email.p...](https://link.juejin.cn?target=https%3A%2F%2Fwww.eisfunke.com%2Fres%2Femail.png "https://www.eisfunke.com/res/email.png") **P.S. 原文作者没有审校过本译文,且译者在翻译本内容时带有个人对原文的理解。可能理解有误,麻烦请在评论区指出!**

相关推荐
香蕉可乐荷包蛋8 分钟前
浅入ES5、ES6(ES2015)、ES2023(ES14)版本对比,及使用建议---ES6就够用(个人觉得)
前端·javascript·es6
未来之窗软件服务42 分钟前
资源管理器必要性———仙盟创梦IDE
前端·javascript·ide·仙盟创梦ide
liuyang___2 小时前
第一次经历项目上线
前端·typescript
西哥写代码2 小时前
基于cornerstone3D的dicom影像浏览器 第十八章 自定义序列自动播放条
前端·javascript·vue
清风细雨_林木木2 小时前
Vue 中生成源码映射文件,配置 map
前端·javascript·vue.js
FungLeo3 小时前
node 后端和浏览器前端,有关 RSA 非对称加密的完整实践, 前后端匹配的代码演示
前端·非对称加密·rsa 加密·node 后端
雪芽蓝域zzs3 小时前
JavaScript splice() 方法
开发语言·javascript·ecmascript
不灭锦鲤3 小时前
xss-labs靶场第11-14关基础详解
前端·xss
不是吧这都有重名3 小时前
利用systemd启动部署在服务器上的web应用
运维·服务器·前端
霸王蟹3 小时前
React中巧妙使用异步组件Suspense优化页面性能。
前端·笔记·学习·react.js·前端框架