UWP 手绘视频创作工具技术分享系列 - SVG 的解析和绘制

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 原文:UWP 手绘视频创作工具技术分享系列 - SVG 的解析和绘制本篇作为技术分享系列的第一篇,详细讲一下 SVG 的解析和绘制,这部分功能的研究和最终实现由团队的 @黄超超 同学负责,感谢提供技术文档和支持。
原文: UWP 手绘视频创作工具技术分享系列 - SVG 的解析和绘制

本篇作为技术分享系列的第一篇,详细讲一下 SVG 的解析和绘制,这部分功能的研究和最终实现由团队的 @黄超超 同学负责,感谢提供技术文档和支持。 

首先我们来看一下 SVG 的文件结构和组成

SVG (Scalable Vector Graphics) 是一种可缩放矢量图形,使用 XML 格式来定义,是一种 W3C 标准,图像在放大或改变尺寸的情况下其图形质量不会有所损失。

下面是一个简单的 SVG 的文件结构例子:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg">
<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>
</svg>

从文件结构来看,SVG 确实是一种标准的 XML 格式,而里面的元素,从字面上来看,是一个坐标为(100,50),半径为40,填充色为红色,线条为黑色,线宽为2的圆形。下面我们来看看 SVG 文件里面的基本元素和属性:

1. 结构元素

<defs>, <g>, <svg>, <symbol>, <use>

2. 图形元素

<line>, <circle>, <ellipse>, <polygon>, <polyline>, <rect>, <path> 

这些标签相信大家都不陌生,几乎每种界面语言都有类似的标记。在 SVG 里,最常用的还是<path>, 用它可以表示前面所有的标签。 

3. 特殊元素

<image> :图片,源通常由 base64 string 或 url 表示。它通常出现在这种场景:通过 PhotoShop 编辑一张图片后,导出为 SVG 格式,这时文件里就存在 <image> 标签,之后再导入到 AI 中进行路径编辑,导出为 SVG 格式,就有了一张可以描绘路径,又包含 <image> 底图的 SVG 文件了。

<text> :文本,设置文字内容和字体字号等信息后,就可以在 SVG 中显示这些文字。 <text> 支持 transform 属性,可以旋转缩放文字,同时还支持 style, css 代码可以直接添加进来。

完整的元素列表参考这里:https://developer.mozilla.org/zh-CN/docs/Web/SVG/element

4. 元素的若干属性

opacity, fill, stroke, stroke-width, stroke-miterlimit, fill-opacity, stroke-opacity, fill-rule, stroke-dasharray, stroke-dashoffset, stroke-linecap, stroke-linejoin, transform

这些都不难理解,代表了元素的透明度,填充,线条,变换等,因为 SVG 是 W3C 标准,所以以上这些外观属性,在 CSS 中都有对应的属性。另外,SVG 还支持其他的属性类型,如动画事件/动画定时/关键帧动画/图形属性/过滤器等,十分强大。

完整的属性列表参考这里:https://developer.mozilla.org/zh-CN/docs/Web/SVG/attribute

来看一个例子:自上而下,分别包含了 两个矩形,一个圆形,一个椭圆,一条直线,一条折线,一个多边形和一条自定义 path。

<?xml version="1.0" standalone="no"?>
<svg width="200" height="250" version="1.1" viewBox="0 0 200 250" xmlns="http://www.w3.org/2000/svg">
  <rect x="10" y="10" width="30" height="30" stroke="black" fill="transparent" stroke-width="5"/>
  <rect x="60" y="10" rx="10" ry="10" width="30" height="30" stroke="black" fill="transparent" stroke-width="5"/>
  <circle cx="25" cy="75" r="20" stroke="red" fill="transparent" stroke-width="5"/>
  <ellipse cx="75" cy="75" rx="20" ry="5" stroke="red" fill="transparent" stroke-width="5"/>
  <line x1="10" x2="50" y1="110" y2="150" stroke="orange" fill="transparent" stroke-width="5"/>
  <polyline points="60,110 65,120 70,115 75,130 80,125 85,140 90,135 95,150 100,145"
      stroke="orange" fill="transparent" stroke-width="5"/>
  <polygon points="50,160 55,180 70,180 60,190 65,205 50,195 35,205 40 190 30 180 45 180"
      stroke="green" fill="transparent" stroke-width="5"/>
  <path d="M20,230 Q40,205 50,230 T90,230" fill="none" stroke="blue" stroke-width="5"/>
</svg>

这里对上面的示例代码做一些补充说明:

计量单位 width height x y 等没有显示指定单位,这时我们认为单位就是 px。也可以明确指定单位 in cm 等,这时会根据当前设备的环境来换算为 px 显示。

viewBox 定义了画布上可以显示的区域,格式为 “x y width height”,如上图的 viewBox=“0 0 200 250”,从(0,0)点开始,宽高 200 * 250的区域,SVG 的 width=“200”,height=“250”,所以当前缩放比是1. 如果 SVG width=“400” height=“500”,则会有两倍的放大效果。

path 和其他元素的对比 在 SVG 中 path 是最常用的元素,和 polyline 做对比,path 也可以通过 d 的设置完成一样的折线或曲线,而且只需要很少的点就可以创建平滑的曲线,但 polyline 需要设置大量的点才能达到平滑的效果。所以从制作难度和缩放效果看,path 是更好的选择。

接下来看一下 SVG 的绘制过程

首先说明绘制的两个基本原则:

1. 解析顺序和绘制顺序一致,都要遵守 XML 中元素的位置排列。借用上面的例子,SVG 中元素在 XML 中有固定的排列顺序,我们解析时会遵守这个顺序,绘制时同样也会遵守这个顺序。也就是说先出现的元素,会出现在绘制的底层,而后出现的元素,会出现在绘制的顶层,如果元素间位置有重叠,则会出现顶层元素遮挡底层元素的情况。

2. 子节点会继承父节点的一些属性,如 opacity,transform 等。这点在绘制时需要特别注意,opacity 等静态属性需要继承,而 transform 等属性需要做矩阵变换才能得到子节点最终 transform。

来画手绘视频中对 SVG 的处理过程

处理中遇到的一些特殊情况和处理

1、解析SVG文档时,忽略DTD验证

    虽然是 DTD 是 XML 解析的标准验证方式,但是很多工具制作的 SVG,DTD 会缺失,所以解析时应该忽略 DTD 验证,不然会直接造成解析错误

2、解析SVG文档时,一些元素的属性值可能有多种分隔/表明方式

    多边形的点集,元素的 transform,都是一个数字集合,集合的分割方式可能是 “空格”,“,” 也可能是其他符号,所以在解析时需要兼容多种分割方式。

    颜色的表示,长度单位等,也可能会出现多种形式,如颜色有已知颜色和颜色值等形式,都需要做兼容。

3、元素的某些属性会继承父级元素  

    transform,透明度等属性,都需要考虑父级元素的继承关系。transform 会复杂一些,transform [3*2] 的 矩阵,会包括缩放/平移/旋转 等信息,子元素的平移信息,需要和父级元素做缩放相乘后,再做平移。

4、元素属性的默认值

     很多工具导出的 SVG,是会忽略一些属性的,而这些属性如果没有值,我们是没办法正确显示的。所以我们需要针对它们设置默认值。例如 fill 默认应该是 none,stroke 默认是 black,stroke-width 默认为1px,fill-rule 默认为 nonzero。这里重点说一下 fill-rule,它分为 evenodd 和 nonzero 两种方式:

    EvenOdd:确定一个点是否位于填充区域内的规则,具体方法是从该点沿任意方向画一条无限长的射线,然后计算该射线在给定形状中因交叉而形成的路径段数。 如果该数为奇数,则点在内部;如果为偶数,则点在外部。

    Nonzero:确定一个点是否位于路径填充区域内的规则,具体方法是从该点沿任意方向画一条无限长的射线,然后检查形状段与该射线的交点。 从零开始计数,每当线段从左向右穿过该射线时加1,而每当路径段从右向左穿过该射线时减 1。 计算交点的数目后,如果结果为零,则说明该点位于路径外部。 否则,它位于路径内部。

5、解析顺序与渲染顺序,描边与填色的顺序

     解析顺序和渲染顺序必须一致,并且和 XML 中的顺序一致,否则会出现错误的遮挡现象和绘制顺序倒转。描边和填色的顺序,基本原则是,单个元素的描边完成后,操作填色,然后再操作下一个元素。当然这里的填色可以灵活控制,比如保存所有填色,等所有描边完成后,一次性填色。

6、包含<image>标签的绘制

    包含 <image> 标签的 SVG,处理起来会有些特殊的地方。这种 SVG 的存在,一般是画师通过 PS 编辑图片后,再导入 AI 中生成的 SVG。处理这种 SVG 的绘制时,基本思路是:解析 <image> 标签,当做 SVG 的底图,用一个透明遮罩挡住;然后解析后面的 <path> 标签,这是只需要解析 path 和 stroke,不需要 fill,用这里的 path 去涂抹底图,涂抹过的地方,透明遮罩失效,底图露出,就达到了涂抹出底图线条的目的。按照这个思路把底图涂抹出来,类似刮刮卡的感觉。

 

到这里,SVG 的基本知识、解析和绘制原理就介绍完了,当然这只是很基础的过程,在后面我们会整理出一些很特殊的 SVG 格式的解析和绘制思路,届时和大家分享,谢谢。

 

目录
相关文章
|
6天前
|
物联网 调度 vr&ar
鸿蒙HarmonyOS应用开发 |鸿蒙技术分享HarmonyOS Next 深度解析:分布式能力与跨设备协作实战
鸿蒙技术分享:HarmonyOS Next 深度解析 随着万物互联时代的到来,华为发布的 HarmonyOS Next 在技术架构和生态体验上实现了重大升级。本文从技术架构、生态优势和开发实践三方面深入探讨其特点,并通过跨设备笔记应用实战案例,展示其强大的分布式能力和多设备协作功能。核心亮点包括新一代微内核架构、统一开发语言 ArkTS 和多模态交互支持。开发者可借助 DevEco Studio 4.0 快速上手,体验高效、灵活的开发过程。 239个字符
155 13
鸿蒙HarmonyOS应用开发 |鸿蒙技术分享HarmonyOS Next 深度解析:分布式能力与跨设备协作实战
|
1月前
|
数据采集 JSON 数据格式
深入解析:使用Python爬取Bilibili视频
本文介绍了如何使用Python编写脚本自动化下载Bilibili视频。通过requests等库获取视频和音频URL,使用ffmpeg合并音视频文件,最终实现高效下载。注意遵守网站爬虫政策和法律法规。
266 4
|
1月前
|
安全 程序员 API
|
1月前
|
自然语言处理 并行计算 数据可视化
免费开源法律文档比对工具:技术解析与应用
这款免费开源的法律文档比对工具,利用先进的文本分析和自然语言处理技术,实现高效、精准的文档比对。核心功能包括文本差异检测、多格式支持、语义分析、批量处理及用户友好的可视化界面,广泛适用于法律行业的各类场景。
|
2月前
|
数据安全/隐私保护 流计算 开发者
python知识点100篇系列(18)-解析m3u8文件的下载视频
【10月更文挑战第6天】m3u8是苹果公司推出的一种视频播放标准,采用UTF-8编码,主要用于记录视频的网络地址。HLS(Http Live Streaming)是苹果公司提出的一种基于HTTP的流媒体传输协议,通过m3u8索引文件按序访问ts文件,实现音视频播放。本文介绍了如何通过浏览器找到m3u8文件,解析m3u8文件获取ts文件地址,下载ts文件并解密(如有必要),最后使用ffmpeg合并ts文件为mp4文件。
|
2月前
|
机器学习/深度学习 编解码 算法
深入解析MaxFrame:关键技术组件及其对视频体验的影响
【10月更文挑战第12天】随着流媒体服务和高清视频内容的普及,用户对于视频质量的要求越来越高。为了满足这些需求,许多技术被开发出来以提升视频播放的质量。其中,MaxFrame是一种旨在通过一系列先进的图像处理算法来优化视频帧的技术。本文将深入探讨构成MaxFrame的核心组件,包括运动估计、超分辨率重建以及时间插值算法,并讨论这些技术如何协同工作以改善视频播放效果。
48 1
|
2月前
|
存储 前端开发 JavaScript
前端模块化打包工具的深度解析
【10月更文挑战第13天】前端模块化打包工具的深度解析
|
2月前
|
JSON JavaScript 前端开发
深入解析ESLint配置:从入门到精通的全方位指南,精细调优你的代码质量保障工具
深入解析ESLint配置:从入门到精通的全方位指南,精细调优你的代码质量保障工具
104 0
|
2月前
|
程序员 开发者 Python
深度解析Python中的元编程:从装饰器到自定义类创建工具
【10月更文挑战第5天】在现代软件开发中,元编程是一种高级技术,它允许程序员编写能够生成或修改其他程序的代码。这使得开发者可以更灵活地控制和扩展他们的应用逻辑。Python作为一种动态类型语言,提供了丰富的元编程特性,如装饰器、元类以及动态函数和类的创建等。本文将深入探讨这些特性,并通过具体的代码示例来展示如何有效地利用它们。
58 0
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
77 2

热门文章

最新文章

推荐镜像

更多