五种关键帧高级玩法第五期(10倍高清不花大麦端选座)
五种关键帧高级玩法第五期(10倍高清不花大麦端选座)
2024-11-22 07:46:52  作者:吖頭扌曳  网址:https://m.xinb2b.cn/tech/hxv272191.html


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

责编 | 夕颜

出品 | CSDN(ID:CSDNnews)


背景介绍

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


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

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

SVG 渲染性能优化;

SVG 如何与业务场景结合;

如何将 CSS 能力应用到 SVGKit,保持(iOS\Android\H5)一致性。


大麦 C 端场景下 SVG 应用

1. SVG 介绍

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


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

2. SVGKit 使用

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


图 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 标签和属性


图 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 编辑复杂度,做了一些 png\jpg 图的 嵌入,一般图片都不大,以下 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 父节点,实现换色,细节流程如下


图 4 CSS 着色原理与时序图

3)大麦端选座渲染效果


图 5 CSS 着色渲染效果

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

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

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


图 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 版本声明头下面添加如下代码块:

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

<!DOCTYPE note SYSTEM "note.dtd"> 一个 DTD 的内容示例:

<!ELEMENT note (to,from,heading,body)><!ELEMENT to (#PCDATA)><!ELEMENT from (#PCDATA)><!ELEMENT heading (#PCDATA)><!ELEMENT body (#PCDATA)>

其中:

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

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

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

4)例如在 DTD 中声明

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

5)如何校验

在完成 DTD 文件的编写后,就是使用 DTD 了,1、 一般使用代码解析的方式,进行 DTD 对 xml 的规范性校验,首先在 svg 的头部加入:<!DOCTYPE svg SYSTEM "svg_note.dtd">然后 在解析 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", handler); xr.parse(new InputSource(is));

其中,必须设置 setValidating(true);才能使 DTD 校验 xml 生效,为方面使用,提供了可以动 态读取 dtd 的方式,为不需要将 dtd 信息添加到 svg 的文件中:执行 Java -jar 命令,传入两个参 数:一个是 svg 的全路径;一个在同目录下的 dtd 的文件名(带扩展名)。

5. 选座性能优化

1)性能调研:APP 端/H5 上渲染如何解决 10 万座位渲染,端侧通过组件复用,手机设备 性能天然还是不错的,加上我们通过预加载资源与分区加载结合方式,点击区域后进行绘制策 略,避免一次性加载全量 10 万数据,也给用户更好的交互体验,然而 H5 侧,浏览器就不那么 流畅了,随着 H5 技术发展,H5 新特性的支持,通过实践使用 SVG 方案,每个座位都用一个 svg 元素显示,由于 svg 的矢量特性,缩放无锯齿,展现效果比较好,但也就支持到 3 万左右的 座位,座位再多也会出现渲染慢和缩放卡顿等问题。Svg 的每个元素也算是一个浏览器的 dom, dom 数量一多起来,达到 3 万到 10 万,浏览器渲染显然不行。

如何减少 dom 节点,又能显示 这么多内容呢?很容易就能想到用 Canvas 来绘制座位,无论在 Canvas 绘制多少元素,在浏览 器都是一个元素,这样就很好解决了 dom 数量的问题,网上能搜到多个应用比较多的开源 Canvas 组件,能实现绘制元素的实时更新,还支持元素的鼠标/手势时间响应。但是都有一个问题,基 本上的原理都是采用帧刷新重绘 Canvas 画布的方式来实现视图更新,确定采用 Canvas svg 渲 染座位图,模拟了 10 万座位的渲染并实现了缩放拖拽等操作,达到了预期的效果。


图 7 选座性能优化-预加载


图 8 端选座性能交互图

6. SVG 场馆彩虹图实现

1)SVG 彩虹图介绍:

在售票选座业务中,需要为用户显示场馆图(SVG 格式),给用户一个场馆的整体印象, 同时方便用户选择场馆的看台,进而展示看台座位进行选座。但是,在使用彩虹图展示场馆图之 前,场馆图的看台区域仅展示看台当前可售座位中的最高票价对应的颜色进行展示,如下图所示:


图 9 非彩虹场馆图

每个看台都是单一颜色的,不能反映出当前看台中可售的座位的价格分布情况,很容易迷 惑用户,造成每个看台只有一种票价的印象,同时不方便用户快速定位他的目标价位所在的区 域。为了准确的反映出场馆每个看台的价格情况,需要将看台中所售的所有的座位的价格展示 出来,因此,采用彩虹图的形式。目标效果如下所示:


图 10 彩虹场馆图

每个区域的所有的座位价格以彩虹的形式显示出来,相比以前的只显示最高票价的颜色, 彩虹图可以清晰的展示每个区域中座位的价格情况。

2)总体思路:在每个看台区域中以彩虹图形式展示多个颜色,就需要将每个看台区域进行划分,放弃之前用一个这类的绘制标签来展示一个看台区域,一个区域内应该包含多个排,对每个排按照座位价格进行着色,进而对每个看台进行同样的处理,总体上形成彩虹样式展示。因此,一个看台区域,应该是多个 svg 标签组合而成的。如图:


图 11 SVG 文件说明

对 SVG 底图进行改造,将老的一个 SVG 标签代表一个看台区域的形式,改造成每个看台 区域由标签进行包裹的多个标签的组合。

为了方便降级,处理不显示彩虹图的业务需求,同时约定标签下的第一个标签,表示整个 区域,同时不再解析渲染后面的排信息。

3)算法生成彩虹图方案 a)介绍:

彩虹图生成算法主要是通过座位的分布和座位的票档圈出一个看台中相同票档座位的范 围,然后生成一个 path 路径。将这些 path 路径加入到 svg 底图中去并且和相应的票档绑定,就 能实现一个区域多种颜色的效果。

b)步骤如下:

对看台中所有排和座位进行分组排序;

②计算看台方向;

③获取同种颜色座位边界;

④计算色块的方向;

⑤获取色块的路径;

⑥生成看台的彩虹图效果;

⑦遍历所有看台生成完整的彩虹图。首先将某个看台所有座位按排分组,然后将排按排号从小到大进行排序。数据结构如下:


图 12 看台编号与座位号示例

座位数据是必备的基础数据,后续一切的计算都依赖于座位数据。通过第一排和第二排座位的相对位置算出看台的方向。

比如:拿到 1 排 1 号和 2 排 1 号座位的坐标,从 2 排 1 号向 1 排 1 号画一条射线,这个射线 的角度就当做看台的方向。

后期如果在生产 SVG 的时候将舞台位置标记出来的话就可以利用舞台来确定看台方向。


图 13 看台方向-1

每个看台的座位分布可以分成两种,一排一种价格和一排多种价格。其中一排一种价格的情况就以同色最后一排为边界。如下图绿色的线。一排多种价格的情况就需要把每一排不同颜色转换处的那两个点记录下来连成边界线。如下图红色和黄色的线。


图 14 看台方向-2

红黄绿三条线所在的座位就是我们需要的色块边界。拿到色块边界座位数组之后还需要知道色块的角度。一排同色的色块方向就直接使用看台

的方向。一排多色的色块方向计算方法如下:


图 15 确定颜色区域-1

将第一个座位 P1 和最后一个座位 P2 连线,取这个线段的垂直线 a1 和 a2。用这两条垂直 线分别和看台方向取夹角。夹角小于 90 度的垂直线的角度作为色块的方向。图中 a1 就是色块 的方向。得到色块边界和色块方向后就可以计算色块 path 的路径了。

①得到包含这个看台 path 路径的最小矩形 rect (图 1);

②从上一步获取的座位边界数组中取四个点分别为:第一个点 P1,第二个点 P2,倒数第二 个点 P3,最后一个点 P4 (图 2);

③由 P2 向 P1 方向做一条射线得到和 rect 的交点 A1,由 P3 向 P4 方向做一条射线得到和

rect 的交点 A2 (图 2);

④根据色块方向获取色块路径的几个关键点:A1 A2 A3 (图 2);

⑤将几个关键点和座位边界所有点连接起来生成一个闭合的路径(图 3 橙色线框)。


图 16 确定颜色区域-2

拿到所有色块路径后就可以将色块填充对应的颜色并且按顺序叠加到看台上形成彩虹图效果。

色块的叠加方式如下:色块的生成顺序是 path1->path2->path3->path4,然后倒序叠加到看台 上 path4->path3->path2->path1。最后就是遍历所有的看台,生成一张完整的彩虹图。


图 17 确定颜色区域-3


总结

本文主要讲解了大麦核心链路选座 SVG 应用,并结合实际场景做了一些创新尝试,包括:丰富 SVG 应用的业务场景、SVG 标签属性及扩展、CSS 着色、渲染性能优化等,目的是让端解析接近浏览器解析效果,并提供更好的端选座性能体验。


☞斩获GitHub 2000 Star,阿里云开源的 Alink 机器学习平台如何跑赢双11数据“博弈”?| AI 技术生态论

☞2020 年,AI 芯片内存哪家强?☞拜托,别再问我什么是 B 树了☞程序员为什么应该旗帜鲜明地反对“最佳实践”?

☞半小时训练亿级规模知识图谱,亚马逊AI开源知识图谱嵌入表示框架DGL-KE

☞“出道” 5 年采用率达 78%,Kubernetes 的成功秘诀是什么?

☞警惕!新骗术出现:这些虚假二维码生成器已成功盗取 4.6 万美元!

今日福利:评论区留言入选,可获得价值299元的「2020 AI开发者万人大会」在线直播门票一张。 快来动动手指,写下你想说的话吧。

  • 清朝的宁古塔有什么用(清朝时期的宁古塔为什么被称为人间地狱)
  • 2024-11-22清朝时期的宁古塔为什么被称为人间地狱清朝宫廷剧中,经常会看到一些官员被皇帝发配至宁古塔披甲为奴甄嬛传中甄嬛的父亲甄远道就曾被雍正皇帝发配到宁古塔,甄嬛得知此事以后心如刀绞宁古塔在清朝就好像人间炼狱,环境恶劣,有去无回,被发配到那里比判死。
  • 新能源汽车评论精华帖 马上评新能源汽车
  • 2024-11-22新能源汽车评论精华帖 马上评新能源汽车澎湃特约评论员朱昌俊中国汽车流通协会日前公布的数据显示,1月份,我国新能源乘用车终端市场销量再创历史新高,新能源乘用车市场占比增大而刚刚过去的2021年,我国新能源汽车销量超过350万辆,每卖出8辆新。
  • 巴特勒出场介绍(巴特勒出席猫王活动)
  • 2024-11-22巴特勒出席猫王活动|(1/5)1905电影网讯美国洛杉矶时间1月7日,演员奥斯汀·巴特勒出席电影《猫王》问答活动,为第80届金球奖做准备演员奥斯汀·巴特勒出席电影《猫王》问答活动在这部电影里,传奇歌手“猫王”和音乐经纪。
  • 家庭版水煮肉片简单好做还好吃(懒人版水煮肉片)
  • 2024-11-22懒人版水煮肉片中午回家做饭,楼下姐姐在院子里等着我,她新买的火锅底料挺不错的,给我两袋我很少买这一类调料,自然也很少用它,姐姐用心用意给我,当然还是要尝尝嘛火锅底料不一定都用来煮火锅,偷懒用它做个菜煮个粉也挺好的重。
  • 厨房橱柜如何设计尺寸(厨房装修中橱柜尺寸大全)
  • 2024-11-22厨房装修中橱柜尺寸大全通常,我们把橱柜分为地柜、吊柜两部分,由于吊柜高度取决于地柜高度所以今天先从地柜高度说起地柜,承载水槽、灶台,为备餐、装盘提供操作台,是实现各个工作区核心功能的基础那么,地柜多高合适?一般的,橱柜商给。
  • 阿笠博士可以做什么(关于阿笠博士的几个有趣小秘密)
  • 2024-11-22关于阿笠博士的几个有趣小秘密似乎自从007系列开始以后,每一位英勇非凡的侦探旁边总会有一位异想天开,总能拿出些什么奇妙发明的大发明家存在作为《名侦探柯南》中颇为出彩的配角,阿笠博士是第一个知道柯南真实身份的人,也发明了不少道具帮。
  • 儿童脑瘫的护理方法(小儿脑瘫日常护理应该注意些什么问题呢)
  • 2024-11-22小儿脑瘫日常护理应该注意些什么问题呢小儿脑瘫就是一种比较严重的脑部疾病,这种疾病要做到早发现早治疗,同时患者要做好这种疾病的护理,那么小儿脑瘫日常护理应该注意哪些呢?请看下面的介绍首先是生活护理,孩子的身体和平时不太一样,所以需要注意,。
  • 酸菜鸭的做法
  • 2024-11-22酸菜鸭的做法主料:鸭子半只酸菜一把辅料:油适量冰糖适量姜片适量生抽适量老抽适量小米辣一个做法:1.鸭子焯水,捞起备用2.酸菜洗好,切好,干锅烘干水分3.热油,下姜片4.加入鸭子,炒香5.加入酸菜,小米辣6.调味,。