公交车上荫蒂添的好舒服的电影-公用玩物(np双xing总受)-公用小荡货芊芊-公与妇仑乱hd-攻把受做哭边走边肉楼梯play-古装一级淫片a免费播放口

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

頁面截圖html2canvas、dom-to-image、html-to-image、modern-screenshot

freeflydom
2024年2月27日 9:57 本文熱度 1978

需求背景

頁面上有大量的圖表,用戶的述求是能對頁面截屏從而直接分享給別人。

那么就有小伙伴要發(fā)問了,為什么不直接把頁面鏈接分享給別人呢?

首先,頁面可能有權(quán)限校驗(yàn),被分享的人可能沒有該頁面的訪問權(quán)限,而圖片不會有這個(gè)問題;其次,實(shí)踐表明,如果分享的是鏈接,用戶的點(diǎn)擊意愿很低,如果不是直接相關(guān)的人往往不會點(diǎn)開鏈接查看,而如果是圖片的話,非常直觀,往往第一眼就傳遞了很多信息給被分享的人。

那么又有小伙伴要發(fā)問了,既然如此,為何不讓用戶自己裝一個(gè)截屏軟件自己截算了?

考慮兩個(gè)點(diǎn),第一是不一定所有用戶都有一個(gè)好用的截屏的軟件(特別是在Mac上,大伙應(yīng)該深有體會),并且頁面如果需要滾動截屏,用戶的操作就會比較麻煩,因此頁面上能提供一個(gè)一鍵截屏的按鈕就十分便利了;第二是如果由頁面提供截圖能力,可以很好地定制最終圖片上所呈現(xiàn)的頁面,比如可以調(diào)整一下布局,修改某些元素。

不過需要注意的是,我們要實(shí)現(xiàn)的截屏并不是一個(gè)真正的截屏,而是相當(dāng)于dom的快照,針對傳入的dom生成圖片。

方案調(diào)研

那么咱就來研究研究,市面上都有哪些截屏的方案。

后端方案

一種比較常見的方案,是在服務(wù)端使用puppeteer(或者playwright啥的)起一個(gè)無頭瀏覽器,渲染完頁面后截圖返回給前端,比如金山文檔就是這么做的。

但是吧,這種方案的缺陷很明顯。首先毋庸置疑的是,服務(wù)端的壓力會變大,成本會變高;其次,最終生成的圖片往往與用戶所看到的頁面有些出入,比如金山文檔的截屏,如果源文檔是些奇奇怪怪的字體,最終生成的圖片里的字體就會是默認(rèn)字體,另外布局什么的也可能會不一致;

源文檔:

生成的圖片:

那么后端方案優(yōu)點(diǎn)也就與缺點(diǎn)一一對應(yīng),首先是對用戶設(shè)備的消耗較小,性能較差的設(shè)備也能使用;其次是對于同一頁面,后端方案生成圖片能夠完全一致,不會因?yàn)橛脩舻臋C(jī)型不同導(dǎo)致頁面布局發(fā)生變化,而且更重要的一點(diǎn)是,生成圖片基本上都依賴于canvas,而canvas這東西有個(gè)坑,它對寬、高、面積有一定的限制,并且不同瀏覽器、不同設(shè)備的限制還不太一樣,并且同一設(shè)備同一瀏覽器也會因?yàn)橛脩舻脑O(shè)備可用資源受到影響,在生成canvas之前也不能拿到這個(gè)限制,這個(gè)限制在IOS設(shè)備上最為嚴(yán)重(有意思的是canvas是蘋果提出的標(biāo)準(zhǔn)),參考javascript - Maximum size of a  element - Stack Overflow,因此采用后端方案能夠保證結(jié)果的一致性。

前端方案

有的小伙伴會說了,瀏覽器自帶截屏功能的,直接用多好呀。是的,瀏覽器有一個(gè)截屏功能,但是我們在JS代碼里并沒法直接調(diào)用,并且瀏覽器自帶的截屏,也無法實(shí)現(xiàn)上述所說的修改頁面元素的能力。

瀏覽器自帶截屏:

那么比較靠譜的前端截屏方案其實(shí)就兩種,一種自己實(shí)現(xiàn)渲染,將dom一一渲染到canvas上后生成圖片,比如html2canvas;另一種是借助foreignObject,將svg繪制到canvas上再生成圖片,代表作為dom-to-image

html2canvas

html2canvas可以說是最古老的前端截屏實(shí)現(xiàn)方案了,也稱得上是獨(dú)一檔的實(shí)現(xiàn)。它的原理簡單來說就是克隆傳入的dom,遍歷克隆樹,通過getBoundingClientRect獲取元素的位置、大小,getComputedStyle獲取元素樣式,然后使用canvas的底層API,一點(diǎn)一點(diǎn)畫出來的。

可想而知,這個(gè)過程是多么復(fù)雜,相當(dāng)于自己實(shí)現(xiàn)了一套渲染引擎,并且css越來越復(fù)雜,想要完全繪制到canvas,夠嗆,所以html2canvas現(xiàn)在有一個(gè)很大的缺點(diǎn)就是對css的支持不夠好。

另外,由于它自建了一套渲染,需要處理的情況非常多,所以包體積相當(dāng)大,官網(wǎng)標(biāo)注的gzip壓縮后也有45kB。

除了上述原因外,真正讓我放棄這個(gè)庫的原因是,它太老了,它真的太老了,作為一個(gè)十幾年前的庫,它現(xiàn)在已經(jīng)年久失修,上次更新都是兩年前,而且看著只是文檔修改。

并且已經(jīng)堆積了800+ issue沒有處理,基本上是不維護(hù)狀態(tài)了。

更有意思的是,即使這個(gè)庫已經(jīng)存在了十幾年,并且有大量頁面將其應(yīng)用到了生產(chǎn)環(huán)境,其中不乏一些大公司產(chǎn)品,比如騰訊文檔(別問我怎么知道的,問就是我寫的),但是它的作者仍在Readme里邊寫到:

dom-to-image

dom-to-image的基本原理十分簡單,不需要做什么復(fù)雜的渲染,利用到了svg元素的foreignObject:

只需要把dom丟到foreignObject里邊,就會在svg里邊渲染出來,因?yàn)槭菫g覽器的標(biāo)準(zhǔn),也不用擔(dān)心對css的支持不夠友好:

其實(shí),到這一步,你會發(fā)現(xiàn)已經(jīng)達(dá)到將dom轉(zhuǎn)成圖片的目的了,svg本來就是圖片。但是你可能會需要其他格式的圖片,并且這樣生成的svg體積實(shí)在是大了點(diǎn),包含了大量冗余的信息。所以這里還是用到canvas,通過drawImage把svg畫到canvas上,再通過canvas的toDataUrl生成圖片鏈接。

從體積上看,不到10kB,是完全可以接受的:

看看它的代碼倉庫,可以看到已經(jīng)七八年不更新了,并且有200+ issue沒有處理,也基本上處于不維護(hù)狀態(tài)了。:

如果能夠滿足需求,也不是不能用,遺憾的是,不太能滿足我的需求。

首先是資源跨域問題,其實(shí)資源本身是支持跨域的,但是原始html中的標(biāo)簽沒有加上crossorigin屬性,導(dǎo)致生成圖片時(shí)會報(bào)跨域錯(cuò)誤,像頁面里的圖片、外鏈css啥的得做點(diǎn)特殊處理才能用。另外還有些奇奇怪怪的問題,可以看看issue,反正是不太能用。

dom-to-image-more

dom-to-image-more聽名字也能聽出來是fork的dom-to-image,解決了dom-to-image的部分bug,增加了一些能力。最重要的能力應(yīng)該是解決了上述提到的跨域問題,它把link標(biāo)簽做了一下攔截,使用fetch去請求對應(yīng)的src,加上了跨域配置,然后再對返回結(jié)果進(jìn)行處理。另外還有一個(gè)有意思的點(diǎn),在dom-to-image中,獲取元素的樣式是通過document.getComputedStyle拿到每個(gè)dom節(jié)點(diǎn)的樣式,然后通過行內(nèi)樣式插入到對應(yīng)的標(biāo)簽上,會導(dǎo)致最后生成的圖片上包含了大量的行內(nèi)樣式,體積自然就比較大;而dom-to-image-more做了一個(gè)優(yōu)化,利用沙盒獲取到了元素的默認(rèn)樣式,再和getComputedStyle作比較,只插入不同于默認(rèn)樣式的屬性,從而極大地減小了圖片的體積,自然而然,這個(gè)復(fù)雜度高了點(diǎn),生成圖片的耗時(shí)稍微長點(diǎn)。

體積很理想,不到6kB:

之前看最新的更新在兩年前,但是近期好像又有更新,說明還是有人在維護(hù)的:

但是最終還是沒有用它,因?yàn)橛袀€(gè)痛點(diǎn),在我的場景下用了很多icon,而這些icon都是svg格式的,它們通過defs - SVG定義了一次,然后使用時(shí)都是通過 - SVG引用的;但是這個(gè)庫沒有處理這種情況,導(dǎo)致生成圖片時(shí)只復(fù)制了use元素,而沒有將其對應(yīng)的defs元素復(fù)制過去,從而導(dǎo)致最終生成的圖片上丟失了這些icon。

html-to-image

html-to-image也是fork的dom-to-image,修了部分bug,增加了一些能力。這個(gè)庫相較于dom-to-image,特點(diǎn)是優(yōu)化了文件結(jié)構(gòu),增加typescript支持,對比上述的dom-to-image-more,處理好了svg use和svg defs的情況,在有use的情況下會去找到對應(yīng)的defs元素并添加進(jìn)來。但是,它沒有解決跨域問題。

另外還有個(gè)痛點(diǎn),之前提到的icon,它們的樣式吧,上面我們提到了,是通過getComputedStyle獲取到,然后插入到行內(nèi)樣式實(shí)現(xiàn)的;對于普通的dom元素而言,這樣做沒有問題,因?yàn)檫@些dom使用的地方就是它們定義的地方;但是對于svg defs和svg use這樣的元素而言,在定義時(shí)它的樣式就已經(jīng)被行內(nèi)樣式寫死了,使用的時(shí)候就沒辦法覆蓋定義時(shí)的樣式,導(dǎo)致我的彩色icon全變成黑色了:

原圖:

生成的圖片:

看了下源代碼,確實(shí)沒有針對這點(diǎn)進(jìn)行處理,所以還是放棄了,另外可想而知的是,像webcomponent這樣定義和使用分離的情況,估計(jì)也存在樣式不能覆蓋的問題。

modern-screenshot

modern-screenshot也是基于dom-to-image,但它不是直接fork的dom-to-image,而是上面提到的html-to-image,所以相當(dāng)于是dom-to-image的孫子輩了。

這個(gè)庫既然是fork的html-to-image,自然也就繼承了html-to-image良好的文件結(jié)構(gòu)以及優(yōu)秀的ts支持;并且這個(gè)庫有意思的是,它還整合了dom-to-image-more的優(yōu)化,不會產(chǎn)生跨域的問題了;對于svg use和svg defs,它更進(jìn)一步,復(fù)用已有的defs,減小了生成圖片的體積;另外還有個(gè)點(diǎn),它用到了webworker并行地發(fā)起網(wǎng)絡(luò)請求。

東抄抄西補(bǔ)補(bǔ),modern-screenshot是目前我看到的效果最理想的前端截屏方案,并且這個(gè)庫的作者仍在維護(hù):

最近的更新發(fā)生在三周前,包體積gzip壓縮后不到10kB,完全可以接受。

美中不足的是,這個(gè)庫依然沒有解決上述提到的svg use樣式不能覆蓋問題。其實(shí)想想也明白,通過getComputedStyle再寫入行內(nèi)樣式的方式,這個(gè)問題是避免不了的。不過,考慮到svg defs元素一般都是icon在使用,而這些icon一般來說不會被外界樣式所影響,所以針對svg defs和svg use標(biāo)簽,我們不通過getComputedStyle獲取其樣式,而是直接使用dom.cloneNode獲取的樣式,這樣就不會寫死行內(nèi)樣式,從而解決了這個(gè)問題。于是給該項(xiàng)目提了一個(gè)PR,也順利合入:

當(dāng)然這種解法并不嚴(yán)謹(jǐn),但是絕大部分情況下應(yīng)該夠用,至少在我的場景下已經(jīng)足夠滿足需求,因此最終我也是選擇了使用modern-screenshot來實(shí)現(xiàn)截屏的需求。


作者:超級無敵大怪獸
鏈接:https://juejin.cn/post/7339671825646338057
來源:稀土掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。



該文章在 2024/2/27 9:57:06 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

主站蜘蛛池模板: 国产午夜精品av一区二区麻豆 | 成人国产一区二区三区精品不卡 | 东京热在线 | 精品亚洲v乱码一区二区 | 91久久香蕉国产线看观看软件 | 国产美女裸体无遮挡免费视频 | 国产成人精品免费视频大全可播 | 2025国产精品国产精华 | av在线播放大全 | a亚洲国产v高清不卡 | 变态sm天堂无码专区 | 国产极品美女高潮无套在线观看 | 91精品国产情侣高潮露脸清 | 国产精品视频一区国模私拍 | 成人亚洲性情网站www在线观看 | 丰满人妻一区二区三区免费视频 | 精品无码国产一区 | 国产欧美高日韩精品久久一区二区 | 精品无码人妻一区二区三区不卡 | 国产精品成人a区在线观看 国产精品成人h视频 | 国产在线麻豆 | 动漫3d精品一区二区三区乱码 | 国产成人精品一区二区三区无码 | 18黑白丝水手服自慰 | 国产精品成人av在线观看 | 国产精品爆乳在线播放 | 国产精品极品在线观看 | 国模αv人体视频 | 国产成人欧美精品视频app | 国产裸体歌舞一区二区视频 | 国产麻豆精品成人免费视频 | 成人国产精品视频 | 国产大波视频在线播放 | 极品熟女少妇av免费久久自慰 | 国产av毛片影院精品资源 | 国产成人午夜福利在线 | 国产黄片按摩视频 | 国产精品亚洲专区无码导航 | 国产精品无码久久久久一区二区 | 国产精品亚洲日韩一区二区 | 国产成人无码一区二区三区 |