摘要:本次技術(shù)調(diào)研來(lái)源于項(xiàng)目中的一個(gè)重要功能需求實(shí)現(xiàn)微信長(zhǎng)按網(wǎng)頁(yè)保存為截圖。小結(jié)是目前實(shí)現(xiàn)網(wǎng)頁(yè)保存為圖片功能的綜合最佳選擇。
本次技術(shù)調(diào)研來(lái)源于H5項(xiàng)目中的一個(gè)重要功能需求:實(shí)現(xiàn)微信長(zhǎng)按網(wǎng)頁(yè)保存為截圖。
這里有個(gè)栗子(請(qǐng)用微信打開(kāi),長(zhǎng)按圖片即可保存):3分鐘探索你的知識(shí)邊界
將整個(gè)網(wǎng)頁(yè)保存為圖片是一個(gè)十分有趣的功能,常見(jiàn)于H5活動(dòng)頁(yè)的結(jié)尾頁(yè)分享。以下則是項(xiàng)目中調(diào)研和踩坑的一些小結(jié)和匯總。
現(xiàn)有已知能夠?qū)崿F(xiàn)網(wǎng)頁(yè)保存為圖片的方案包括:
方案1:將DOM改寫為canvas,然后利用canvas的toDataURL方法實(shí)現(xiàn)將DOM輸出為包含圖片展示的data URI
方案2:使用html2canvas.js實(shí)現(xiàn)(可選搭配Canvas2Image.js實(shí)現(xiàn)網(wǎng)頁(yè)保存為圖片)
方案3:使用rasterizeHTML.js實(shí)現(xiàn)
1.2 解決方案的選擇
方案1:需要手動(dòng)計(jì)算每個(gè)DOM元素的Computed Style,然后需要計(jì)算好元素在canvas的大小位置等屬性。
方案1難點(diǎn):
相當(dāng)于完全重寫了整個(gè)頁(yè)面的布局樣式,增加了工作量。
由于canvas中沒(méi)有的對(duì)象概念,對(duì)于元素豐富、布局復(fù)雜的頁(yè)面,不易重構(gòu)。
所有DOM元素改寫進(jìn)canvas會(huì)帶來(lái)一些困難,例如:難以支持響應(yīng)式,圖片元素清晰度不佳和文字點(diǎn)擊區(qū)域識(shí)別問(wèn)題等。
方案2:該類功能中Github上stars最多(至今仍在維護(hù)),Stack Overflow亦有豐富的討論。只需簡(jiǎn)單調(diào)用html2canvas方法并設(shè)定配置項(xiàng)即可。
方案3:該方案的限制較多,目前僅支持3類可轉(zhuǎn)為canvas的目標(biāo)格式: 頁(yè)面url,html字符串和document對(duì)象。
小結(jié): html2canvas是目前實(shí)現(xiàn)網(wǎng)頁(yè)保存為圖片功能的綜合最佳選擇。
1.3 html2canvas的使用方法官方GitHub:https://github.com/niklasvh/h...
以下描述針對(duì)html2canvas版本是0.5.0-beta4
1.3.1 實(shí)現(xiàn)保存為圖片的第一步:html轉(zhuǎn)為canvas基于html2canvas.js可將一個(gè)元素渲染為canvas,只需要簡(jiǎn)單的調(diào)用html2canvas(element[, options]);即可。下列html2canvas方法會(huì)返回一個(gè)包含有元素的promise:
html2canvas(document.body).then(function(canvas) { document.body.appendChild(canvas); });1.3.2 實(shí)現(xiàn)保存為圖片的第二步:canvas轉(zhuǎn)image
上一步生成的canvas即為包含目標(biāo)元素的元素對(duì)象。實(shí)現(xiàn)保存圖片的目標(biāo)只需要將canvas轉(zhuǎn)image即可。
這里的轉(zhuǎn)換方案有2種:
方案1:基于原生canvas的toDataURL方法將canvas輸出為data: URI類型的圖片地址,再將該圖片地址賦值給
方案2:使用第三方庫(kù)Canvas2Image.js,調(diào)用其convertToImage方法即可(GitHub)
實(shí)際上,Canvas2Image.js也是基于canvas.toDataURL的封裝,相比原生的canvas API對(duì)于轉(zhuǎn)為圖片的功能上考慮更為具體(未壓縮的包大小為7.4KB),適合項(xiàng)目使用。
二、生成圖片的清晰度優(yōu)化方案 2.1 基礎(chǔ)的清晰度優(yōu)化方案最終圖片的清晰度取決于第一步中html轉(zhuǎn)換成的canvas的清晰度。
現(xiàn)有解決方案參考;
html5 canvas在高倍屏下變模糊的處理辦法
html5 canvas繪制圖片模糊的問(wèn)題
其基本原理為:
將canvas的屬性width和height屬性放大為2倍(或者設(shè)置為devicePixelRatio倍),最后將canvas的CSS樣式width和height設(shè)置為原先1倍的大小。
例如:希望在html中實(shí)際顯示的寬高分別為160px,90px則可作如下設(shè)置
參考上述文檔具體的使用案例如下;
convert2canvas() { var shareContent = YourTargetElem; var width = shareContent.offsetWidth; var height = shareContent.offsetHeight; var canvas = document.createElement("canvas"); var scale = 2; canvas.width = width * scale; canvas.height = height * scale; canvas.getContext("2d").scale(scale, scale); var opts = { scale: scale, canvas: canvas, logging: true, width: width, height: height }; html2canvas(shareContent, opts).then(function (canvas) { var context = canvas.getContext("2d"); var img = Canvas2Image.convertToImage(canvas, canvas.width, canvas.height); document.body.appendChild(img); $(img).css({ "width": canvas.width / 2 + "px", "height": canvas.height / 2 + "px", }) }); }2.2 進(jìn)階的清晰度優(yōu)化方案
上述設(shè)置可以解決通常情況下圖片不清晰的問(wèn)題,不過(guò)探索并沒(méi)有結(jié)束。
實(shí)際在我們的項(xiàng)目中,即使作出2.1節(jié)的設(shè)置后,大果粒一般的渲染結(jié)果依然尷尬。
下面直接給出3條進(jìn)一步的優(yōu)化策略:
更改百分比布局為px布局(如果原先是百分比布局的話)
關(guān)閉canvas默認(rèn)的抗鋸齒設(shè)置
設(shè)置模糊元素的width和height為素材原有寬高,然后通過(guò)transform: scale進(jìn)行縮放。這里scale的數(shù)值由具體需求決定。
基本原理
如果原來(lái)使用百分比設(shè)置元素寬高,請(qǐng)更改為px為單位的寬高,避免樣式二次計(jì)算導(dǎo)致的模糊
默認(rèn)情況下,canvas的抗鋸齒是開(kāi)啟的,需要關(guān)閉抗鋸齒來(lái)實(shí)現(xiàn)圖像的銳化(MDN: imageSmoothingEnabled )
除了canvas可以通過(guò)擴(kuò)大2倍寬高然后縮放至原有寬高來(lái)提高清晰度,對(duì)于DOM中其他的元素也可以使用css樣式的scale來(lái)實(shí)現(xiàn)同樣的縮放
例: html2canvas配置
convert2canvas() { var cntElem = $("#j-sec-end")[0]; var shareContent = cntElem;//需要截圖的包裹的(原生的)DOM 對(duì)象 var width = shareContent.offsetWidth; //獲取dom 寬度 var height = shareContent.offsetHeight; //獲取dom 高度 var canvas = document.createElement("canvas"); //創(chuàng)建一個(gè)canvas節(jié)點(diǎn) var scale = 2; //定義任意放大倍數(shù) 支持小數(shù) canvas.width = width * scale; //定義canvas 寬度 * 縮放 canvas.height = height * scale; //定義canvas高度 *縮放 canvas.getContext("2d").scale(scale, scale); //獲取context,設(shè)置scale var opts = { scale: scale, // 添加的scale 參數(shù) canvas: canvas, //自定義 canvas // logging: true, //日志開(kāi)關(guān),便于查看html2canvas的內(nèi)部執(zhí)行流程 width: width, //dom 原始寬度 height: height, useCORS: true // 【重要】開(kāi)啟跨域配置 }; html2canvas(shareContent, opts).then(function (canvas) { var context = canvas.getContext("2d"); // 【重要】關(guān)閉抗鋸齒 context.mozImageSmoothingEnabled = false; context.webkitImageSmoothingEnabled = false; context.msImageSmoothingEnabled = false; context.imageSmoothingEnabled = false; // 【重要】默認(rèn)轉(zhuǎn)化的格式為png,也可設(shè)置為其他格式 var img = Canvas2Image.convertToJPEG(canvas, canvas.width, canvas.height); document.body.appendChild(img); $(img).css({ "width": canvas.width / 2 + "px", "height": canvas.height / 2 + "px", }).addClass("f-full"); }); }
例: DOM元素樣式:?
.targetElem {width: 54px;height: 142px;margin-top:2px;margin-left:17px;transform: scale(0.5)}三、含有跨域圖片的配置
由于canvas對(duì)于圖片資源的同源限制,如果畫布中包含跨域的圖片資源則會(huì)污染畫布,造成生成圖片樣式混亂或者h(yuǎn)tml2canvas方法不執(zhí)行等問(wèn)題。
以下主要解決兩類跨域的圖片資源:包括已配置過(guò)CORS的CDN中的圖片資源和微信用戶頭像圖片資源。
3.1 針對(duì)CDN中的圖片的配置要求CDN的圖片配置好CORS。CDN配置好后,通過(guò)chrome開(kāi)發(fā)者工具可以看到響應(yīng)頭中應(yīng)含有Access-Control-Allow-Origin的字段。
開(kāi)啟html2canvas的useCORS配置項(xiàng)。即作如下設(shè)置:?
var opts = {useCORS: true}; html2canvas(element, opts);
注意:
如果沒(méi)有開(kāi)啟html2canvas的useCORS配置項(xiàng),html2canvas會(huì)正常執(zhí)行且不會(huì)報(bào)錯(cuò),但是不會(huì)輸出對(duì)應(yīng)的CDN圖片
(已測(cè)試同時(shí)包含CDN的圖片和本地圖片的資源的頁(yè)面,但是只有本地圖片能夠被正常渲染出來(lái))
如果需要將微信平臺(tái)中的用戶頭像一并保存為圖片,3.1的方案無(wú)能為力??赏ㄟ^(guò)配置服務(wù)端代理轉(zhuǎn)發(fā)(forward)實(shí)現(xiàn),此處不贅述。
其他注意事項(xiàng) 1. margin的遮擋問(wèn)題微信中,喚出長(zhǎng)按保存圖片的菜單要求長(zhǎng)按的對(duì)象直接是
而事實(shí)上,引發(fā)遮擋的并不只是非
canvas2img默認(rèn)保存圖片的格式為png,而在安卓版微信中所生成的圖片盡管能長(zhǎng)按喚出保存圖片的菜單,但是無(wú)法正確保存到本地相冊(cè)。 解決方案:設(shè)置canvas2img的生成圖片格式配置項(xiàng)為jpeg即可。
3. JPEG的黑屏問(wèn)題設(shè)置canvas2img輸出格式為jpeg,會(huì)有一定幾率導(dǎo)致生成的圖片包含大量的黑色塊。可能的解決方案:縮減部分圖片元素的體積和尺寸大小。
4. 不能保留動(dòng)效在圖片的轉(zhuǎn)化前,必須停止或者刪除動(dòng)效后才能正確渲染出圖片,否則生成的圖片是破裂的。
參考文獻(xiàn)CanvasRenderingContext2D.drawImage()
Add dpi/scale options for custom resolution
HTMLCanvasElement.toDataURL()
html5 canvas在高倍屏下變模糊的處理辦法
Canvas實(shí)現(xiàn)保存圖片到本地
html2canvas截圖如何解決跨域的問(wèn)題
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/51336.html
摘要:本次技術(shù)調(diào)研來(lái)源于項(xiàng)目中的一個(gè)重要功能需求實(shí)現(xiàn)微信長(zhǎng)按網(wǎng)頁(yè)保存為截圖。小結(jié)是目前實(shí)現(xiàn)網(wǎng)頁(yè)保存為圖片功能的綜合最佳選擇。 本次技術(shù)調(diào)研來(lái)源于H5項(xiàng)目中的一個(gè)重要功能需求:實(shí)現(xiàn)微信長(zhǎng)按網(wǎng)頁(yè)保存為截圖。 這里有個(gè)栗子(請(qǐng)用微信打開(kāi),長(zhǎng)按圖片即可保存):3分鐘探索你的知識(shí)邊界 將整個(gè)網(wǎng)頁(yè)保存為圖片是一個(gè)十分有趣的功能,常見(jiàn)于H5活動(dòng)頁(yè)的結(jié)尾頁(yè)分享。以下則是項(xiàng)目中調(diào)研和踩坑的一些小結(jié)和匯總。 ...
摘要:本次技術(shù)調(diào)研來(lái)源于項(xiàng)目中的一個(gè)重要功能需求實(shí)現(xiàn)微信長(zhǎng)按網(wǎng)頁(yè)保存為截圖。小結(jié)是目前實(shí)現(xiàn)網(wǎng)頁(yè)保存為圖片功能的綜合最佳選擇。 本次技術(shù)調(diào)研來(lái)源于H5項(xiàng)目中的一個(gè)重要功能需求:實(shí)現(xiàn)微信長(zhǎng)按網(wǎng)頁(yè)保存為截圖。 這里有個(gè)栗子(請(qǐng)用微信打開(kāi),長(zhǎng)按圖片即可保存):3分鐘探索你的知識(shí)邊界 將整個(gè)網(wǎng)頁(yè)保存為圖片是一個(gè)十分有趣的功能,常見(jiàn)于H5活動(dòng)頁(yè)的結(jié)尾頁(yè)分享。以下則是項(xiàng)目中調(diào)研和踩坑的一些小結(jié)和匯總。 ...
摘要:本次技術(shù)調(diào)研來(lái)源于項(xiàng)目中的一個(gè)重要功能需求實(shí)現(xiàn)微信長(zhǎng)按網(wǎng)頁(yè)保存為截圖。以下主要解決兩類跨域的圖片資源包括已配置過(guò)的中的圖片資源和微信用戶頭像圖片資源。 本次技術(shù)調(diào)研來(lái)源于H5項(xiàng)目中的一個(gè)重要功能需求:實(shí)現(xiàn)微信長(zhǎng)按網(wǎng)頁(yè)保存為截圖。 這里有個(gè)栗子(請(qǐng)用微信打開(kāi),長(zhǎng)按圖片即可保存):3分鐘探索你的知識(shí)邊界 將整個(gè)網(wǎng)頁(yè)保存為圖片是一個(gè)十分有趣的功能,常見(jiàn)于H5活動(dòng)頁(yè)的結(jié)尾頁(yè)分享。以下則是項(xiàng)目中...
摘要:本次技術(shù)調(diào)研來(lái)源于項(xiàng)目中的一個(gè)重要功能需求實(shí)現(xiàn)微信長(zhǎng)按網(wǎng)頁(yè)保存為截圖。以下主要解決兩類跨域的圖片資源包括已配置過(guò)的中的圖片資源和微信用戶頭像圖片資源。 本次技術(shù)調(diào)研來(lái)源于H5項(xiàng)目中的一個(gè)重要功能需求:實(shí)現(xiàn)微信長(zhǎng)按網(wǎng)頁(yè)保存為截圖。 這里有個(gè)栗子(請(qǐng)用微信打開(kāi),長(zhǎng)按圖片即可保存):3分鐘探索你的知識(shí)邊界 將整個(gè)網(wǎng)頁(yè)保存為圖片是一個(gè)十分有趣的功能,常見(jiàn)于H5活動(dòng)頁(yè)的結(jié)尾頁(yè)分享。以下則是項(xiàng)目中...
摘要:本次技術(shù)調(diào)研來(lái)源于項(xiàng)目中的一個(gè)重要功能需求實(shí)現(xiàn)微信長(zhǎng)按網(wǎng)頁(yè)保存為截圖。以下主要解決兩類跨域的圖片資源包括已配置過(guò)的中的圖片資源和微信用戶頭像圖片資源。 本次技術(shù)調(diào)研來(lái)源于H5項(xiàng)目中的一個(gè)重要功能需求:實(shí)現(xiàn)微信長(zhǎng)按網(wǎng)頁(yè)保存為截圖。 這里有個(gè)栗子(請(qǐng)用微信打開(kāi),長(zhǎng)按圖片即可保存):3分鐘探索你的知識(shí)邊界 將整個(gè)網(wǎng)頁(yè)保存為圖片是一個(gè)十分有趣的功能,常見(jiàn)于H5活動(dòng)頁(yè)的結(jié)尾頁(yè)分享。以下則是項(xiàng)目中...
閱讀 2598·2021-10-25 09:45
閱讀 1257·2021-10-14 09:43
閱讀 2314·2021-09-22 15:23
閱讀 1542·2021-09-22 14:58
閱讀 1946·2019-08-30 15:54
閱讀 3554·2019-08-30 13:00
閱讀 1371·2019-08-29 18:44
閱讀 1585·2019-08-29 16:59