JS如何實現頁面截圖功能例項程式碼
"頁面截圖"是前端經常遇到的需求,比如頁面生成海報,彈窗圖片分享等,因為瀏覽器沒有原生的截圖API,所以需要藉助canvas來實現匯出圖片實現需求。
可行性方案
- 方案1: 將 DOM 改寫成 canvas ,呼叫canvas的toBlob或者toDataURL方法http://www.cppcns.com即nEdTi刻上傳到七牛雲或伺服器
- 方案2: 使用第三方庫html2canvas.js實現 canvas , 在不更改頁面已有DOM的情況下優雅生產canvas
解決方案的選擇
方案1:需要手動計算每個DOM元素的Computed Style,然後需要計算好元素在canvas的大小位置等屬性。
方案1難點
- 需要棄用已有的html頁面,改用canvas重寫。
- 頁面結構層複雜的情況下用canvas寫,不易重構。
- 有一定canvas基礎。
方案2:該專案在github上stars已有兩萬多start,作者仍在積極維護。API非常簡單,在已有專案中開箱即用。
html2canvas
因為是常見的需求,所以社群會有成熟的解決方案,首先試試社群的解決方案。
<div id="capture" style="padding: 10px; background: #f5da55"> <h4 style="color: #000; ">Hello world!</h4> </div>
html2canvas(document.querySelector("#capture")).then(canvas => { document.body.appendChild(canvas) });
以上是官網的例項用法。在網頁上出現了一個新的 canvas DOM。接下來我們只需要把canvas轉換成圖片就好。這裡使用canva原生的toDataURL和toBlob方法上次到七牛雲。
使用時需要注意。此處如果生產的畫布中有跨域圖片,需要配置allowTaint為true。
如果是原生canvas實現,canvas需要所有跨域圖片請求完成才可繪製。有兩種解決方案
- 方案1:在html上寫好img標籤,src寫好對應的圖片url。缺點很明顯,會汙染頁面的佈局結構。
- 方案2:使用js,使用new Image()的方式。設定src到對應的圖片url,在onload回撥中處理相關操作。優點:可行性最高,不過有回撥地獄的問題。我們用Promise改寫一下
function asyncImage(url) { const img = new Image(); img.src = url; img.setAttribute('crossOrigin','anonymous'); return new Promise((resolve,reject) => { img.onload = () => resolve(img); img.onerror = reject; }); }
好的,大功告成~是不是可以交付需求了呢?開開心心提測,但是在移動端測試的時候發現生產的圖片非常模糊。這樣是不行的,明顯low了許多(測試不給過orz)。
github有相應的解決方案 傳送門 ,這個回答也是解決很多人的問題
基本原理:將canvas寬高放大兩倍。把css把canvas的style設定成1倍大小。
var shareContent = YourTargetElem; var width = shareContent.offsetWidth; var height = shareContent.offsetHeight; var canvas = document.createElement("canvas"); var scale = 2 || window.devicePixelRatio ; //也可以使用裝置畫素比 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",}) });
原理我們已經知道了,實際操作之後影象也確實清晰了很多。但是問題還是沒有解決掉。
縮小雖然提高了清晰度,但是我們需要的圖片是原始比例的大小。。
最終多次嘗試無果後,選擇放棄使用框架。直接用原生canvas擼一個!
canvas繪製
我們知道,在高清屏的裝置下,任何繪製canvas中的影象、文字、線條、形狀都可能會出現模糊的問題。可通過引入 GitHub 中的 hidpi-canvas 有效地解決。
- 首先去 GitHub nEdTi下載 hidpi-canvas.js 檔案:傳送門;
- 在專案中引入 hidpi-canvas.js 檔案;
- 呼叫 getPixelRatio() 函式,得到 ratio 值;
- 在 drawImage() 中,將 width 和 height 乘以 ratio;
- 最終的canvas匯出為Blog,轉換成檔案物件上傳七牛雲。
核心程式碼如下
function asyncImage(url) { const img = new Image(); img.src = url; img.setAttribute('crossOrigin','anonymous'); return new Promise((resolve,reject) => { img.onload = () => resolve(img); img.onerror = reject; }); } async function drawCanvas(){ var canvas = document.querySelector('canvas'); var context = canvas.getContext('2d'); var ratio = getPixelRatio(context); // 關鍵程式碼 canvas.width = 300 * ratio; // 畫布寬度 canvas.height = 300 * ratio; // 畫布高度 var divWidth = 300 * ratio; // 用於內容居中 var divHeight = 300 * ratio; // 用於內容居中 const image = await asyncImage('picUrl') const imgWidth = 550 const imgHeight = 300 context.drawImage(this,50,imgWidth * ratio,imgHeight * ratio) // Some other code const Blob = canvas.toBlob((Blob)=>{程式設計客棧 //上傳七牛雲 }); }
最終生成的圖片終於清晰了...只需要根據dom的offsetWidth等適配不同螢幕就可以了。
總結
如果對圖片的清晰度要求不高,或者圖片需求是生成縮圖的情況下。採用 html2canvawww.cppcns.coms 是非常不錯的選擇。
否則,還是用canvas繪製出的圖片更清晰。
到此這篇關於JS如何實現頁面截圖功能的文章就介紹到這了,更多相關JS頁面截圖功能內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!