自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

前端生成海報(bào)圖技術(shù)選型與問(wèn)題解決

開發(fā)
本篇文章主要聚焦海報(bào)圖分享這個(gè)形式,探討純前端在H5&小程序內(nèi),合成海報(bào)到下載到本地、分享至社交平臺(tái)整個(gè)流程中可能遇到的問(wèn)題,以及如何解決。

一、引言

絕大多數(shù)的電商平臺(tái)都會(huì)設(shè)計(jì)分享裂變的功能,激勵(lì)用戶進(jìn)行分享,這是一種拉新促活的常見措施。提到分享裂變,就免不了需要生成用戶專屬的分享鏈接或者專屬海報(bào)。當(dāng)然分享推廣的形式多種多樣,有文本鏈接、網(wǎng)頁(yè)鏈接、圖片邀請(qǐng)碼、小程序、音視頻等等。

本篇文章主要聚焦海報(bào)圖分享這個(gè)形式,探討純前端在H5&小程序內(nèi),合成海報(bào)到下載到本地、分享至社交平臺(tái)整個(gè)流程中可能遇到的問(wèn)題,以及如何解決。

二、選型參考

2.1 實(shí)現(xiàn)方式

根據(jù)海報(bào)圖生成渠道的差異,可以將海報(bào)圖生成分為:客戶端生成、前端生成和服務(wù)端生成,以下是從技術(shù)實(shí)現(xiàn)、兼容性、生成速度和功能受限四個(gè)維度進(jìn)行的對(duì)比:

圖片

  • 對(duì)于排版復(fù)雜的場(chǎng)景: 建議使用服務(wù)端Node.js渲染的方式【如Puppeteer圖片生成】;
  • 對(duì)于排版簡(jiǎn)單,但用戶請(qǐng)求并發(fā)大的場(chǎng)景:建議使用前端或客戶端生成海報(bào)圖;
  • 對(duì)于需多端投放,樣式動(dòng)態(tài)更新的場(chǎng)景:建議使用前端生成海報(bào)圖;
  • 對(duì)于疊加用戶交互的場(chǎng)景:建議使用客戶端原生繪制的方式生成。

本篇文章著重聚焦前端H5 & 小程序內(nèi)生成海報(bào)圖的技術(shù)實(shí)現(xiàn),如果大家對(duì)服務(wù)端、客戶端生成海報(bào)圖的方案感興趣,文末有相關(guān)鏈接可供參考。

2.2 H5 生成海報(bào)圖技術(shù)選型

H5 生成海報(bào)圖常推薦的方案有三種:

(1)html2canvas:基于頁(yè)面中存在且可用的DOM結(jié)構(gòu)、樣式,構(gòu)建“截圖”,繪制到canvas畫布中。

下面是html2canvas的技術(shù)解析,詳細(xì)講解可以參考文末鏈接。

圖片

(2)dom-to-image:將DOM 節(jié)點(diǎn)序列化為XML,包裝到SVG中,再轉(zhuǎn)為圖片。

下面是dom-to-image的技術(shù)解析,詳細(xì)講解可以參考文末鏈接。

圖片

(3)canvas 純?cè)L制

以下是示例代碼,這里不做贅述

圖片

html2canvas和dom-to-image都是用于在canvas的基礎(chǔ)上封裝的庫(kù),由于底層實(shí)現(xiàn)方式的不同,它們各有優(yōu)缺點(diǎn),以下是從幾個(gè)維度進(jìn)行的優(yōu)缺點(diǎn)對(duì)比。

圖片

那么如何快速的確認(rèn)當(dāng)前的項(xiàng)目應(yīng)該用哪個(gè)組件庫(kù)呢,有沒(méi)有必要逐個(gè)去驗(yàn)證,這里給到幾點(diǎn)建議:

  • 如果需要處理的頁(yè)面比較復(fù)雜或者需要支持SVG圖片渲染,在html2canvas中可能更好一些。
  • 如果需要穩(wěn)定的文字、圖片渲染能力或者處理結(jié)構(gòu)化數(shù)據(jù)的能力,在dom-to-image中可能更好一些。
  • 如果頁(yè)面基本是圖片資源,那么使用原生canvas性能是最好的。

2.3 小程序生成海報(bào)圖技術(shù)選型

與H5類似,小程序生成海報(bào)圖在項(xiàng)目中常用的也有三種方案:

(1)wxml-to-canvas:利用微信小程序提供的canvas組件,將指定的wxml轉(zhuǎn)化成canvas繪圖,然后再將其導(dǎo)出為圖片

詳見:微信小程序wxml-to-canvas官方文檔

圖片

(2)Painter:利用JSX語(yǔ)法,將繪圖的操作轉(zhuǎn)化成繪制命令,并生成對(duì)應(yīng)的canvas繪圖

下圖來(lái)源于Painter 2.0官方介紹

圖片

(3)Canvas/Canvas2D

以下是小程序2D Canvas 官方示例代碼,詳見微信小程序基礎(chǔ)能力/畫布

圖片


  • 從技術(shù)實(shí)現(xiàn)上看,wxml-to-canvas 是基于2d類型的Canvas組件能力,對(duì)基礎(chǔ)庫(kù)有要求,需在2.7.0以上。在canvas2d的基礎(chǔ)上,封裝了繪制text、image和view的能力,提供wxml繪制到canvas和導(dǎo)出圖片的方法。Painter不僅支持2d類型的canvas,同時(shí)兼容了低版本canvas組件。同時(shí)支持更多復(fù)雜樣式的繪制,對(duì)于網(wǎng)絡(luò)素材實(shí)現(xiàn)了一套LRU存儲(chǔ)機(jī)制,無(wú)需重復(fù)下載圖片,并增加了容錯(cuò)機(jī)制。
  • 從使用方法上看,wxml-to-canvas使用相對(duì)較簡(jiǎn)單,只需要在小程序中引入wxml-to-canvas庫(kù),然后傳入需要生成海報(bào)圖的wxml代碼和畫布的寬高即可。而Painter需要在小程序中使用類JSX的語(yǔ)法繪制所有圖形,覆蓋小程序頁(yè)面中相應(yīng)的canvas組件。

針對(duì)兩種不同庫(kù),wxml-to-canvas更適合將已有的wxml結(jié)構(gòu)轉(zhuǎn)換為圖片,對(duì)于復(fù)雜的定制化設(shè)計(jì)需要在wxml中拼接、排版的海報(bào)來(lái)說(shuō),并不是最佳選擇。Painter則更適合在小程序中進(jìn)行復(fù)雜繪制操作。

但從另一個(gè)角度看,如果對(duì)繪制性能要求比較高的業(yè)務(wù)來(lái)說(shuō),wxml-to-canvas 相比Painter更符合訴求。當(dāng)然,如果僅涉及圖片間的快速組合,也可以使用canvas原生繪制的能力,只是要關(guān)注圖像繪制和canvas導(dǎo)出的實(shí)際問(wèn)題。

前面兩個(gè)章節(jié),主要解決在繪制選型上的疑慮,下一步面對(duì)的就是如何解決實(shí)現(xiàn)過(guò)程中出現(xiàn)的問(wèn)題。

三、H5 常見問(wèn)題

3.1  設(shè)計(jì)還原效果

設(shè)計(jì)還原除了關(guān)注最基礎(chǔ)的字體樣式、排版,同時(shí)也要兼顧深色模式適配、字號(hào)大小適配、頁(yè)面縮放、瀏覽器兼容性。這些因素?zé)o疑給前端生成海報(bào)圖帶來(lái)巨大的壓力,下面我也將從提到的這些方面進(jìn)行展開,也可以作為大家選型參考或者解決方案的參考。

當(dāng)業(yè)務(wù)需求涉及復(fù)雜的文本排版,那么建議直接放棄canvas原生繪制,難度大風(fēng)險(xiǎn)大耗時(shí)長(zhǎng)。第三方庫(kù)處理邏輯大同小異,本質(zhì)上都是基于DOM 轉(zhuǎn)為 canvas,但并不是真正的瀏覽器截圖,都會(huì)存在一些共性問(wèn)題。

3.1.1 字體樣式

如下圖所示,當(dāng)前設(shè)備生效的是特殊字體,那么生成海報(bào)圖得到的有可能是特殊字體,出現(xiàn)與設(shè)計(jì)不符,不同用戶生成的海報(bào)圖效果不一致的情況。

圖片

如何規(guī)避這個(gè)問(wèn)題呢?復(fù)制DOM并隱藏,對(duì)復(fù)制的DOM嵌入網(wǎng)絡(luò)字體包,保證設(shè)計(jì)效果。如果是固定文案,也可以采用嵌入圖片的方式。

3.1.2 排版

排版常遇到的問(wèn)題是文本換行、超長(zhǎng)字符打點(diǎn),通常也會(huì)疊加系統(tǒng)字號(hào)大小、頁(yè)面縮放一起出現(xiàn)。

圖片

問(wèn)題1: 文本換行打點(diǎn)怎么辦?

  • 第三方庫(kù)中一般會(huì)有文本換行相關(guān)的處理
    類似html-to-canvas它的處理基于"CanvasRenderingContext2D.measureText()",在繪制時(shí)測(cè)量每個(gè)字符的寬度,進(jìn)行渲染位置的更新。基于這個(gè)處理方案,超長(zhǎng)字符打點(diǎn)的問(wèn)題是很難解決的。
    而dom-to-canvas是基于svg轉(zhuǎn)圖片的方式,天然的具有文本排版處理的能力,這也是這個(gè)庫(kù)的優(yōu)勢(shì)所在。

問(wèn)題2: 那如果疊加頁(yè)面縮放呢?

一般h5都具有頁(yè)面縮放適配的能力,復(fù)制DOM也會(huì)繼承該處理,不會(huì)有太大的影響。

問(wèn)題3: 如果頁(yè)面有設(shè)置大字號(hào)模式,DOM在不同字號(hào)大小下展示樣式有區(qū)別,但是需要導(dǎo)出圖片樣式保持一致呢?

那么就需要在復(fù)制DOM時(shí),針對(duì)字號(hào)大小進(jìn)行逆向處理,比如系統(tǒng)字體將字號(hào)放大1.25倍,在該場(chǎng)景下,復(fù)制DOM時(shí)就需要對(duì)字號(hào)進(jìn)行縮小1.25倍。

3.1.3 適配

深色模式適配,分為兩種:

  • 一種是系統(tǒng)級(jí)別的反色:系統(tǒng)級(jí)別的反色不會(huì)侵入到DOM,復(fù)制的DOM仍然與淺色模式下一致,導(dǎo)出的圖片也不會(huì)受到影響。
  • 一種是自定義樣式的反色:自定義的反色對(duì)DOM樣式有侵入,復(fù)制DOM及其樣式,導(dǎo)出的圖片可能受影響,如下圖所示。只需要在復(fù)制DOM時(shí)將侵入的樣式或者控制深色模式的判斷條件去除即可。

圖片

兼容性適配,與canvas和foreignObject的兼容性相關(guān),一般來(lái)說(shuō),不建議在Android低版本中使用,性能較差。

3.2   跨域問(wèn)題

只要使用canvas繪制圖片,必然繞不過(guò)的就是跨域的問(wèn)題,解決跨域問(wèn)題有以下幾種思路:

  1. 代理服務(wù)器:通過(guò)配置服務(wù)器代理,將原本跨域的圖片請(qǐng)求轉(zhuǎn)為同域的圖片請(qǐng)求。從根源上解決跨域問(wèn)題。針對(duì)圖片來(lái)源單一可控的場(chǎng)景、具備代理配置的能力的業(yè)務(wù)場(chǎng)景,建議采用該方案。
  2. 解決資源跨域:前提需要有權(quán)限訪問(wèn)被請(qǐng)求的跨域服務(wù)器,可以通過(guò)設(shè)置服務(wù)器上的 CORS頭信息“Access-Control-Allow-Origin: *  或者特定域名”來(lái)實(shí)現(xiàn),然后再解決資源的跨域問(wèn)題。下面就聚焦這個(gè)場(chǎng)景,展開介紹下:

3.2.1 crossOrigin

在請(qǐng)求圖片時(shí),需要增加屬性 img.crossOrigin = 'anonymous' ,告知跨域服務(wù)器,本次請(qǐng)求可以匿名訪問(wèn),不需要提供憑證。代碼示例如下圖所示:

圖片

設(shè)置這個(gè)就可以一勞永逸了嗎,并不是,還可能出現(xiàn)圖片緩存引起的請(qǐng)求跨域問(wèn)題:在同一個(gè)頁(yè)面中,如果canvas需要繪制的圖片已經(jīng)加載過(guò)了,瀏覽器會(huì)默認(rèn)緩存下來(lái),當(dāng)canvas使用這張圖片時(shí),瀏覽器會(huì)直接返回緩存的圖片。這時(shí)被緩存后的圖片就不展示CORS請(qǐng)求響應(yīng)頭攜帶Access-Control-Allow-Origin的要求了,就會(huì)導(dǎo)致報(bào)錯(cuò)。

解決方案最簡(jiǎn)單的是給跨域請(qǐng)求追加時(shí)間戳,但這個(gè)方案會(huì)造成資源重復(fù)請(qǐng)求,也可能會(huì)有緩存擊穿的風(fēng)險(xiǎn)。

3.2.2 ajax+Blob/base64

通過(guò)額外發(fā)一次請(qǐng)求,將圖片轉(zhuǎn)為blob或者直接用base64的圖片格式,避免單張圖片頻繁請(qǐng)求。但如果涉及到的圖片比較多,也會(huì)帶來(lái)內(nèi)存壓力問(wèn)題,需要注意資源及時(shí)釋放。代碼示例如下圖所示:

圖片

3.3  生成性能

  1. 控制復(fù)制DOM的數(shù)量 原因:海報(bào)圖的生成耗時(shí)與復(fù)制dom的數(shù)量成正比。
  2. 如果采用的是iframe啟用的方式,減少iframe啟動(dòng)次數(shù)。
  3. 一般組件庫(kù)是基于一個(gè)DOM生成一張海報(bào)圖,如果一次需要生成多張海報(bào)圖,可以合并DOM,啟用一次iframe,批量生成多張圖片。
  4. 分割操作,將文本相關(guān)耗時(shí)的操作前置,最后簡(jiǎn)單的圖片+圖片的合并,使用canvas原生繪制,也是一種提升性能的方案。

四、小程序常見問(wèn)題

4.1 元素繪制

不論是使用哪種方案,在小程序繪制海報(bào)圖時(shí),需要提前設(shè)定好繪制的尺寸,甚至wxml-to-canvas要求為每個(gè)元素設(shè)置固定的寬度和高度,否則會(huì)出現(xiàn)布局錯(cuò)誤。所以自適應(yīng)高度在小程序端是不存在的,對(duì)于排版樣式就進(jìn)行了初步限定。

同時(shí),元素之間是存在層級(jí)關(guān)系的,與書寫的結(jié)構(gòu)強(qiáng)關(guān)聯(lián),這個(gè)要尤為注意。

對(duì)于元素及其樣式的支持是有限的,不同庫(kù)的支持程度也是不一致的,可根據(jù)業(yè)務(wù)進(jìn)行選擇,這里簡(jiǎn)單舉例對(duì)比下:

圖片

4.2 存儲(chǔ)問(wèn)題

以下是wxml-to-canvas的源碼,在繪制圖片時(shí),往往是繪制網(wǎng)絡(luò)圖片,需要從遠(yuǎn)程拉取圖片,轉(zhuǎn)為本地臨時(shí)文件存儲(chǔ)【wx.downloadFile】,canvas繪制取臨時(shí)文件地址【tempFilePath】,然后進(jìn)行繪制。保存圖片時(shí)再將canvas導(dǎo)出為臨時(shí)文件【wx.canvasToTempFilePath】。

圖片

若在小程序內(nèi)觸發(fā)保存圖片到本地【wx.saveImageToPhotosAlbum】,需要進(jìn)行權(quán)限校驗(yàn),這部分需要業(yè)務(wù)自行處理,如下所示。

圖片

如果選擇使用Painter庫(kù)繪制海報(bào)圖,且為了提升性能開啟了LRU存儲(chǔ)機(jī)制,這時(shí)就要關(guān)注緩存文件的有效性,官方也在小程序 LRU 存儲(chǔ)設(shè)計(jì)中進(jìn)行了重點(diǎn)講解。

4.3 生成性能

研究過(guò)Painter源碼的同學(xué)可能關(guān)注到在canvas導(dǎo)出圖片的函數(shù)中,存在一個(gè)300ms的延遲,這個(gè)是為什么呢?300ms這個(gè)延遲可以去掉嗎?

圖片

答案是:這個(gè)邏輯下不可以省略!否則可能出現(xiàn)圖片缺失的問(wèn)題。

Painter提供了canvas2d 接口和canvas舊接口兩套邏輯,而延遲300ms出現(xiàn)在舊接口邏輯體系中。這是因?yàn)榕f接口使用的是downloadFile將網(wǎng)絡(luò)圖片緩存到本地后再進(jìn)行drawImage,而整個(gè)繪制-導(dǎo)出過(guò)程中沒(méi)有監(jiān)聽圖片加載完成的步驟,因此有概率出現(xiàn)圖片未加載完成就直接繪制的情況,進(jìn)而出現(xiàn)內(nèi)容缺失。雖然加入了定時(shí)器延長(zhǎng)時(shí)間,但不同的機(jī)器不同的圖片繪制時(shí)間不同,設(shè)定單一的延遲等待并不能從根本上解決問(wèn)題,反而影響生成圖片的性能。

相應(yīng)的,在canvas2d的體系中則可以通過(guò) Canvas.createImage 創(chuàng)建圖片對(duì)象,并監(jiān)聽圖片的load事件,在回調(diào)之后執(zhí)行ctx.drawImage繪制到canvas中,這樣就可以有效的解決上述問(wèn)題。

針對(duì)這種場(chǎng)景,如果有其他比較好的解決方案,歡迎讀者在評(píng)論區(qū)留言。

ps: 微信官方正在推出Skyline/snapshot的截圖組件,也可以實(shí)現(xiàn)wxml/wxss導(dǎo)出圖片的功能,詳見微信小程序Skyline /snapshot

五、思考總結(jié)

本文主要聚焦前端生成海報(bào)圖的技術(shù)選型,不同選型可能出現(xiàn)的問(wèn)題及其解決思路。期望通過(guò)本篇文章,能夠讓讀者在接收到相關(guān)需求時(shí),對(duì)于一些容易踩坑的點(diǎn)做好前期評(píng)估。如果當(dāng)前正在開發(fā)相關(guān)的需求,遇到相似的問(wèn)題能夠提供一些解決思路。

同時(shí)如果大家有更好的解決方案,歡迎在評(píng)論區(qū)留言。

當(dāng)然,隨著AI技術(shù)的發(fā)展,生成海報(bào)圖可能不再需要通過(guò)代碼邏輯實(shí)現(xiàn)??梢酝ㄟ^(guò)數(shù)據(jù)模型訓(xùn)練,更加智能化的快速生成營(yíng)銷海報(bào)圖,那么以上的問(wèn)題將不再是問(wèn)題。我們也將持續(xù)關(guān)注在ToC業(yè)務(wù)中相關(guān)的實(shí)現(xiàn)方案,與大家一起探討。

參考連接:

  1. html2canvas實(shí)現(xiàn)瀏覽器截圖的原理(包含源碼分析的通用方法)
  2. 前端關(guān)于html2canvas截圖的問(wèn)題?
  3. 使用html2canvas在前端生成圖片
責(zé)任編輯:龐桂玉 來(lái)源: vivo互聯(lián)網(wǎng)技術(shù)
相關(guān)推薦

2009-03-06 10:10:00

廣播風(fēng)暴網(wǎng)絡(luò)

2011-06-27 16:44:59

Qmake

2011-06-13 16:16:32

Qt 中文問(wèn)題

2010-06-17 11:35:24

Ubuntu 修復(fù)Gr

2010-04-28 18:01:15

Unix系統(tǒng)

2011-06-14 13:41:27

muleWSDL

2011-04-29 10:18:34

投影機(jī)

2011-11-28 22:45:19

Nginxsession

2009-12-28 10:56:45

WPF Image

2010-05-05 10:25:24

Unix操作系統(tǒng)

2012-05-09 10:08:41

跨機(jī)房

2010-05-05 14:20:46

AIX CDE

2011-01-21 14:13:10

2023-11-07 18:56:05

2009-06-30 14:02:00

Struts亂碼Eclipse

2011-08-01 17:50:28

Xcode

2010-07-29 15:28:47

Flex安全沙箱

2010-03-30 16:04:34

Linux Nginx

2010-03-30 17:44:24

CentOS系統(tǒng)

2010-04-29 15:46:47

Unix操作系統(tǒng)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)