d3 svg path添加文本_10 倍高清不花!大麦端选座 SVG 渲染
作者 | 阿里文娛無線開發(fā)專家 波濤
責(zé)編 | 夕顏
出品 | CSDN(ID:CSDNnews)
背景介紹
用戶在大麥上購票,需要自行選座。在大型場館下,如何讓 10 萬+座位繪制達(dá)到閃開?這需要技術(shù)在繪制上保證性能流程,在選座渲染上通過技術(shù)手段賦予更多可能性。因此,大麥引用 SVG 繪制技術(shù),并根據(jù)業(yè)務(wù)場景下作了很多優(yōu)化,本文是大麥在用戶端的技術(shù)方案設(shè)計與應(yīng) 用實踐。
10 萬+座位繪制面臨以下挑戰(zhàn)
如何豐富標(biāo)簽樣式及屬性;
SVG 渲染性能優(yōu)化;
SVG 如何與業(yè)務(wù)場景結(jié)合;
如何將 CSS 能力應(yīng)用到 SVGKit,保持(iOSAndroidH5)一致性。
大麥 C 端場景下 SVG 應(yīng)用
1. SVG 介紹
可伸縮矢量圖形 (Scalable Vector Graphics),用來定義用于網(wǎng)絡(luò)的基于矢量的圖形,使用 XML 格式定義圖形,圖像在放大或改變尺寸的情況下其圖形質(zhì)量不會有所損失,是萬維網(wǎng)聯(lián) 盟的標(biāo)準(zhǔn), DOM 和 XSL 之類的 W3C 標(biāo)準(zhǔn)是一個整體,不失真,兼容現(xiàn)有圖片能力前提還 支持矢量(瀏覽器兼容情況),通過瀏覽器很早版本支持情況在主流瀏覽器都支持,SVG 提供的 功能集涵蓋了嵌套轉(zhuǎn)換、裁剪路徑、Alpha 通道、濾鏡效果等能力,它還具備了傳統(tǒng)圖片沒有 的矢量功能,在任何高清設(shè)備都很高清。
圖 1 SVG 與其他格式圖片比較
2. SVGKit 使用
瀏覽器默認(rèn)就支持 SVG 渲染,屬于 XML-Dom 家族系列,但是在移動端上并沒有做原生支 持,還是按照 XML 進(jìn)行的讀取,支持的開源庫也不多,在 IOS 上,目前 OC 版本 SvgKit 還不 錯,官方 Github 也在繼續(xù)維護(hù),雖然更新較慢,通過幾次 patch 提交 PR 還是很快 merge 的, 一些通用屬性和控件支持的不夠完善,需要進(jìn)行定制開發(fā),swift 版本的 macaw 也不錯,在動畫 效果上更加酷炫,目前也正在做 swift 效果遷移到 OC 中,渲染流程如下:
圖 2 SVGKit 渲染加載流程圖
1)SVGKit 有哪些標(biāo)簽?
circle = SVGCircleElement; 【圓形】clipPath = SVGClipPathElement;【層疊路徑】 description = SVGDescriptionElement; 【描述】 ellipse = SVGEllipseElement; 【橢圓】g = SVGGElement; 【容器標(biāo)簽】line = SVGLineElement;【直線】 path = SVGPathElement;【路徑】polygon = SVGPolygonElement;【多角形】 polyline = SVGPolylineElement;【多邊形】 rect = SVGRectElement;【矩形】svg = SVGSVGElement;【SVG 容器標(biāo)簽】 switch = SVGSwitchElement;【選擇】 text = SVGTextElement;【文本】textArea = TinySVGTextAreaElement;【區(qū)域文本】 title = SVGTitleElement;【標(biāo)題】2)擴(kuò)展基于三端統(tǒng)一 SVG 標(biāo)簽和屬性圖 3 SVG 標(biāo)簽屬性擴(kuò)展大圖
3)SVG 標(biāo)簽在 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【解析漸變標(biāo)簽】 SVGKParserPatternsAndGradients【解析圖案】 SVGKParserStyles【解析樣式】SVGKParserSVG【解析 SVG 標(biāo)簽】d)解析 XML 中 CSS 樣式類 SVGKParserStyles :標(biāo)簽解析到生成 Layer 層 1.類:SVGKParserDOM.m: SVGElement. 2.核心思想:SVG 標(biāo)簽渲染流程一、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 分析總結(jié)
SVGKit 版本升級 2.X 升級 3.X-Release,升級后主要是一些屬性的支持度更完善,包括 Text 富文本渲染,字體多樣式支持,還有一些渲染上的優(yōu)化,可通過 patch 提交 查看,比較一下 W3C 下 SVG 圖在 2.X 分支及 3.X 分支的解析及渲染時間,性能能也有提升, 同時增加 image 圖片加載 base64 圖片,加載在線 URL 及本地資源圖片,我們也在 SVGImageElement 中提供擴(kuò) 展 API 增加 Webp 支持,因為 SVG 本身是為矢量圖方案加入 PNG 等圖存在一定模糊情況,不 過運營可能會在底圖上做一些 Logo 展示,為了減少 SVG 編輯復(fù)雜度,做了一些 pngjpg 圖的 嵌入,一般圖片都不大,以下 API:展示 base64 運營位圖片而設(shè)計的
[NSData dataContentWithBase64Str:str]3. 基于 CSS 著色能力
1)為什么用 CSS 著?
SVG 雖然是繪制圖形,原理如同 HTML,是給每一個標(biāo)簽設(shè)置一個單獨 style 好還是通過 CSS Id /class 映射好呢,這個思路和 HTML 處理 STYLE 樣式是一樣的,便于更改和維護(hù),在 性能上也更好,同時增加了 important 屬性,可以更好的配置樣式,可做到運營側(cè)根據(jù)樣式 style 下發(fā)方式達(dá)到更改 SVG 圖效果,可以做到更多活動效果及個性化需求。
2)SVG-CSS 著色渲染過程
SVG 標(biāo)簽基于 CSS 樣式快速應(yīng)用,通過遍歷 DomTree,找到對應(yīng)的 Node 節(jié)點,在給 node 節(jié)點設(shè)置 id 或者 class,然后局部刷新 Tree 父節(jié)點,實現(xiàn)換色,細(xì)節(jié)流程如下
圖 4 CSS 著色原理與時序圖
3)大麥端選座渲染效果
圖 5 CSS 著色渲染效果
4)CSS 著色原理總結(jié)及性能比較 如何確定屬性使用的是 CSS 顏色還是自帶 style 屬性?
當(dāng) SVG 在解析生成 DomTree 后,我們可以根據(jù) CSSStyle 樣式存儲的 CSS 樣式,給 Node 標(biāo)簽設(shè)置 id 及 class,當(dāng)更改 nodeList 后,相當(dāng)于樹結(jié)構(gòu)進(jìn)行了修改,在繪制時候查找屬性會根 據(jù)優(yōu)先策略 id > class > 進(jìn)行查找進(jìn)行屬性賦值,我們根據(jù) CSS 屬性 !important 來設(shè)置最高優(yōu) 先級,這樣就避免了此問題。
端側(cè)渲染流程如下,左側(cè):是基于 node 遍歷后修改,右側(cè)是修改 id/class 方式【推薦】。性能比對:為了兼容 W3C 標(biāo)準(zhǔn),端上增加了 CSS 特殊屬性 important。
圖 6 SVG-Codec 總體性能提升對比
4. SVG 約束 DTD
1)背景介紹
當(dāng) SVG 生產(chǎn)端在制作 SVG 圖,可能會用到 Adobe 等軟件,有很多復(fù)雜屬性及層疊,可能 會產(chǎn)生復(fù)雜 XML 格式,這樣在渲染過程中會造成大量遍歷,影響性能,也有一些特殊屬性, 端上并沒有支持,例如濾鏡、動畫,這樣,我們就需要有一種約束來校驗生產(chǎn)和渲染 SVG 能夠 一致。
2)文檔類型定義
(DTD)可定義合法的 XML 文檔構(gòu)建模塊。它使用一系列合法的元素來定義文檔的結(jié)構(gòu)。
DTD 可被成行地聲明于 XML 文檔中,也可作為一個外部引用。
DTD 被定義在 xml 的 DOCTYPE 聲明中。
3)定義一個名為 note 的 DTD
如果要使用內(nèi)部定義,則在 xml 文件的 xml 版本聲明頭下面添加如下代碼塊:
// DTD 內(nèi)容]> 如果要引用外部 DTD,那么它應(yīng)通過下面的語法被封裝在 一個 DOCTYPE 定義中: 例如,在 xml 文件的 xml 版本聲明頭下面添加如下代碼塊:
一個 DTD 的內(nèi)容示例:
其中:
!ELEMENT note 定義 note 元素有四個元素:"to、from、heading、body"
!ELEMENT to 定義 to 元素為 "#PCDATA" 類型。
PCDATA 的意思是被解析的字符數(shù)據(jù)(parsed character data)。可想象為 XML 元素的開始 標(biāo)簽與結(jié)束標(biāo)簽之間的文本,PCDATA 是會被解析器解析的文本。這些文本將被解析器檢查以 及標(biāo)記,文本中的標(biāo)簽會被當(dāng)作標(biāo)記來處理,而實體會被展開,不過,被解析的字符數(shù)據(jù)不應(yīng) 當(dāng)包含任何 &、< 或者 > 字符;需要使用 &、< 以及 > 實體來分別替換它們。
4)例如在 DTD 中聲明
它表示在和之間可以插入字符或者子標(biāo) 簽,CDATA 的意思是字符數(shù)據(jù)(character data, CDATA 是不會被解析器解析的文本。在這些文 本中的標(biāo)簽不會被當(dāng)作標(biāo)記來對待,其中的實體也不會被展開。
5)如何校驗
在完成 DTD 文件的編寫后,就是使用 DTD 了,1、 一般使用代碼解析的方式,進(jìn)行 DTD 對 xml 的規(guī)范性校驗,首先在 svg 的頭部加入:然后 在解析 svg 時,聲明合法性校驗例如,以 SAX 解析 XML 為例:
SAXParserFactory spf = SAXParserFactory.newInstance; spf.setValidating(true); // 關(guān)鍵設(shè)置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總結(jié)
以上是生活随笔為你收集整理的d3 svg path添加文本_10 倍高清不花!大麦端选座 SVG 渲染的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言怎么删除字符串中的指定字符_Jav
- 下一篇: python循环输入字典_python