d3 svg path添加文本_10 倍高清不花!大麦端选座 SVG 渲染

2d5c552d724c19a8087cde353aeb3309.png

作者 | 阿里文娱无线开发专家 波涛

责编 | 夕颜

出品 | CSDN(ID:CSDNnews)

99dcc20ba57ddb574cecf4082e87f7a7.png

背景介绍

用户在大麦上购票,需要自行选座。在大型场馆下,如何让 10 万+座位绘制达到闪开?这需要技术在绘制上保证性能流程,在选座渲染上通过技术手段赋予更多可能性。因此,大麦引用 SVG 绘制技术,并根据业务场景下作了很多优化,本文是大麦在用户端的技术方案设计与应 用实践。

80e1a5a1898d1870675ae5b5752fc4f0.png

10 万+座位绘制面临以下挑战

  1. 如何丰富标签样式及属性;

  2. SVG 渲染性能优化;

  3. SVG 如何与业务场景结合;

  4. 如何将 CSS 能力应用到 SVGKit,保持(iOSAndroidH5)一致性。

00d1292c0cd62ea5e693f38e794e082d.png

大麦 C 端场景下 SVG 应用

1. SVG 介绍

可伸缩矢量图形 (Scalable Vector Graphics),用来定义用于网络的基于矢量的图形,使用 XML 格式定义图形,图像在放大或改变尺寸的情况下其图形质量不会有所损失,是万维网联 盟的标准, DOM 和 XSL 之类的 W3C 标准是一个整体,不失真,兼容现有图片能力前提还 支持矢量(浏览器兼容情况),通过浏览器很早版本支持情况在主流浏览器都支持,SVG 提供的 功能集涵盖了嵌套转换、裁剪路径、Alpha 通道、滤镜效果等能力,它还具备了传统图片没有 的矢量功能,在任何高清设备都很高清。

dec0a81c80f803ebbeca19ca04518838.png

图 1 SVG 与其他格式图片比较

2. SVGKit 使用

浏览器默认就支持 SVG 渲染,属于 XML-Dom 家族系列,但是在移动端上并没有做原生支 持,还是按照 XML 进行的读取,支持的开源库也不多,在 IOS 上,目前 OC 版本 SvgKit 还不 错,官方 Github 也在继续维护,虽然更新较慢,通过几次 patch 提交 PR 还是很快 merge 的, 一些通用属性和控件支持的不够完善,需要进行定制开发,swift 版本的 macaw 也不错,在动画 效果上更加酷炫,目前也正在做 swift 效果迁移到 OC 中,渲染流程如下:

3dc51dd933689cd18d7b915386305866.png

图 2 SVGKit 渲染加载流程图

1)SVGKit 有哪些标签?

circle = SVGCircleElement; 【圆形】clipPath = SVGClipPathElement;【层叠路径】 description = SVGDescriptionElement; 【描述】 ellipse = SVGEllipseElement; 【椭圆】g = SVGGElement; 【容器标签】line = SVGLineElement;【直线】 path = SVGPathElement;【路径】polygon = SVGPolygonElement;【多角形】 polyline = SVGPolylineElement;【多边形】 rect = SVGRectElement;【矩形】svg = SVGSVGElement;【SVG 容器标签】 switch = SVGSwitchElement;【选择】 text = SVGTextElement;【文本】textArea = TinySVGTextAreaElement;【区域文本】 title = SVGTitleElement;【标题】2)扩展基于三端统一 SVG 标签和属性
1c08cb6370926d2591472719edebe88d.png

图 3 SVG 标签属性扩展大图

3)SVG 标签在 SVGKit 中渲染流程

a)SVGKit 核心渲染原理分析

视图 SVGKFastImageView.m 加载到窗口显示 核心中心处理类,主要加载 SVG 文件资源文件

类:SVGKimage : NSObjectSVGKParseResult* parsedSVG = [parser parseSynchronously]; // 解析 SVGKImage* finalImage = [[SVGKImage alloc] initWithParsedSVG:parsedSVG fromSource:source];

b)分析:

解析 SVG-到合成 ViewLayer初始化 SVGKSource source svg 资源实例 初始化 SVGSVGElement -> DomTree 初始化 SVGDocument -> DomDocument CALayerTree 最终合成的 Layer 树SVGKParser* parser = [SVGKParser newParserWithDefaultSVGKParserExtensions:source]; 开 始解析

c)解析 XML 类 SVGKParser:NSObject 解析 SVG(XML)文件

+(SVGKParser ) newParserWithDefaultSVGKParserExtensions:(SVGKSource )source (SVGKParseResult*) parseSynchronously. 解析异常处理 XML 解析处理XML 解析过程 SAX// 每解析一个 Node 添加到 DOMTree 中. (SVGKParserStyles) SVGKParserDefsAndUse 【解析 useAndDefs 样式】 SVGKParserDOM 【解析 DOM】 SVGKParserGradient【解析渐变标签】 SVGKParserPatternsAndGradients【解析图案】 SVGKParserStyles【解析样式】SVGKParserSVG【解析 SVG 标签】d)解析 XML 中 CSS 样式类 SVGKParserStyles :标签解析到生成 Layer 层 1.类:SVGKParserDOM.m: SVGElement. 2.核心思想:SVG 标签渲染流程一、SVGKImage.m 渲染 核心思想:遍历 DOM 映射到 iOS layer 绘制3.生成 UILayer:-(CALayer *)newCALayerTreeCALayer* newLayerTree = [self newLayerWithElement:self.DOMTree]; CALayer sublayer = [self newLayerWithElement:(SVGElement )child]; [newLayerTree addlayer. Sublayer][element layoutLayer:layer]; [layer setNeedsDisplay];

4)SVGKit 分析总结

SVGKit 版本升级 2.X 升级 3.X-Release,升级后主要是一些属性的支持度更完善,包括 Text 富文本渲染,字体多样式支持,还有一些渲染上的优化,可通过 patch 提交 查看,比较一下 W3C 下 SVG 图在 2.X 分支及 3.X 分支的解析及渲染时间,性能能也有提升, 同时增加 image 图片加载 base64 图片,加载在线 URL 及本地资源图片,我们也在 SVGImageElement 中提供扩 展 API 增加 Webp 支持,因为 SVG 本身是为矢量图方案加入 PNG 等图存在一定模糊情况,不 过运营可能会在底图上做一些 Logo 展示,为了减少 SVG 编辑复杂度,做了一些 pngjpg 图的 嵌入,一般图片都不大,以下 API:展示 base64 运营位图片而设计的

 [NSData dataContentWithBase64Str:str]

3. 基于 CSS 着色能力

1)为什么用 CSS 着?

SVG 虽然是绘制图形,原理如同 HTML,是给每一个标签设置一个单独 style 好还是通过 CSS Id /class 映射好呢,这个思路和 HTML 处理 STYLE 样式是一样的,便于更改和维护,在 性能上也更好,同时增加了 important 属性,可以更好的配置样式,可做到运营侧根据样式 style 下发方式达到更改 SVG 图效果,可以做到更多活动效果及个性化需求。

2)SVG-CSS 着色渲染过程

SVG 标签基于 CSS 样式快速应用,通过遍历 DomTree,找到对应的 Node 节点,在给 node 节点设置 id 或者 class,然后局部刷新 Tree 父节点,实现换色,细节流程如下

b51928a2d6c56ba82f91d5085a587992.png

图 4 CSS 着色原理与时序图

3)大麦端选座渲染效果

ee139b415364a74b27457b350661eef0.png

图 5 CSS 着色渲染效果

4)CSS 着色原理总结及性能比较 如何确定属性使用的是 CSS 颜色还是自带 style 属性?

当 SVG 在解析生成 DomTree 后,我们可以根据 CSSStyle 样式存储的 CSS 样式,给 Node 标签设置 id 及 class,当更改 nodeList 后,相当于树结构进行了修改,在绘制时候查找属性会根 据优先策略 id > class > 进行查找进行属性赋值,我们根据 CSS 属性 !important 来设置最高优 先级,这样就避免了此问题。

端侧渲染流程如下,左侧:是基于 node 遍历后修改,右侧是修改 id/class 方式【推荐】。性能比对:为了兼容 W3C 标准,端上增加了 CSS 特殊属性 important。

de8033f434fcffa28d3fb7f454ad4357.png

图 6 SVG-Codec 总体性能提升对比

4. SVG 约束 DTD

1)背景介绍

当 SVG 生产端在制作 SVG 图,可能会用到 Adobe 等软件,有很多复杂属性及层叠,可能 会产生复杂 XML 格式,这样在渲染过程中会造成大量遍历,影响性能,也有一些特殊属性, 端上并没有支持,例如滤镜、动画,这样,我们就需要有一种约束来校验生产和渲染 SVG 能够 一致。

2)文档类型定义

(DTD)可定义合法的 XML 文档构建模块。它使用一系列合法的元素来定义文档的结构。

DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。

DTD 被定义在 xml 的 DOCTYPE 声明中。

3)定义一个名为 note 的 DTD

如果要使用内部定义,则在 xml 文件的 xml 版本声明头下面添加如下代码块:

// DTD 内容]> 如果要引用外部 DTD,那么它应通过下面的语法被封装在 一个 DOCTYPE 定义中: 例如,在 xml 文件的 xml 版本声明头下面添加如下代码块:

一个 DTD 的内容示例:

 

其中:

!ELEMENT note 定义 note 元素有四个元素:"to、from、heading、body"

!ELEMENT to 定义 to 元素为 "#PCDATA" 类型。

PCDATA 的意思是被解析的字符数据(parsed character data)。可想象为 XML 元素的开始 标签与结束标签之间的文本,PCDATA 是会被解析器解析的文本。这些文本将被解析器检查以 及标记,文本中的标签会被当作标记来处理,而实体会被展开,不过,被解析的字符数据不应 当包含任何 &、< 或者 > 字符;需要使用 &、< 以及 > 实体来分别替换它们。

4)例如在 DTD 中声明

它表示在和之间可以插入字符或者子标 签,CDATA 的意思是字符数据(character data, CDATA 是不会被解析器解析的文本。在这些文 本中的标签不会被当作标记来对待,其中的实体也不会被展开。

5)如何校验

在完成 DTD 文件的编写后,就是使用 DTD 了,1、 一般使用代码解析的方式,进行 DTD 对 xml 的规范性校验,首先在 svg 的头部加入:然后 在解析 svg 时,声明合法性校验例如,以 SAX 解析 XML 为例:

SAXParserFactory spf = SAXParserFactory.newInstance; spf.setValidating(true); // 关键设置SAXParser sp = spf.newSAXParser; XMLReader xr = sp.getXMLReader;XMLParser.SAXHandler handler = new XMLParser.SAXHandler; xr.setContentHandler(handler);xr.setErrorHandler(new SAXErrorHandler); // 输出校验出错的信息xr.setProperty("http://xml.org/sax/properties/lexical-handler
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
d3.js是一个用于数据可视化的JavaScript库,它提供了丰富的功能和工具来创建交互式和动态的数据可视化图表。其中,svgpath标签在d3.js中被称为"可以组成任何形状的形状"。d3.js提供了多种path生成器,可以用来创建不同类型的路径。 以下是一些常用的d3.js svg path生成器: 1. d3.svg.line() - 线path生成器 2. d3.svg.line.radial() - 径向path生成器 3. d3.svg.area() - 区域path生成器 4. d3.svg.area.radial() - 径向区域path生成器 5. d3.svg.arc() - 圆与圆弧path生成器 6. d3.svg.symbol() - 符号path生成器 7. d3.svg.chord() - chord path生成器 8. d3.svg.diagonal() - diagonal path生成器 9. d3.svg.diagonal.radial() - diagonal radial path生成器 这些生成器可以通过调用相应的方法来生成路径,并且还可以使用其他方法来改变其属性。此外,这些生成器还支持链式调用,可以方便地进行多个操作。 范例: ```javascript // 创建一个svg元素 var svg = d3.select("body") .append("svg") .attr("width", 500) .attr("height", 500); // 创建一个线path生成器 var lineGenerator = d3.svg.line(); // 创建一个路径并设置其属性 var path = svg.append("path") .attr("d", lineGenerator([[0, 0], [100, 100], [200, 50]])) .attr("stroke", "black") .attr("fill", "none"); // 创建一个圆与圆弧path生成器 var arcGenerator = d3.svg.arc() .innerRadius(50) .outerRadius(100) .startAngle(0) .endAngle(Math.PI); // 创建一个路径并设置其属性 var path = svg.append("path") .attr("d", arcGenerator()) .attr("transform", "translate(250, 250)") .attr("fill", "red"); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值