本文轉載自【微信公眾號:趣談前端,ID:beautifulFront】經微信公眾號授權轉載,如需轉載與原文作者聯繫
前言
網頁截圖功能目前也是非常常見的需求, 尤其是在在線教育領域. 我們朋友圈的微信海報, 活動海報等, 一般都是運營/市場人員通過設計工具設計而成, 但是如何更好的映射到自己的服務體系裡面, 比如H5頁面中, 植入更多信息收集, 交互能力. 這一塊的應用探索, 頁面截圖是一個非常好的解決方案.
接下來筆者就來復盤一下如何基於網頁, 一鍵生成頁面海報的功能, 並將此能力, 集成到筆者的開源項目H5-Dooring中為編輯器賦能.
正文
在實現具體功能之前, 我們先看看具體的實現效果:
從演示中我們可以看出, 我們最終目標是實現在PC端生成H5頁面的截圖, 所以可能會涉及到以下幾個問題:
如何實現將頁面轉化為圖片如何實現H5效果模擬並截取實際的H5頁面我們可以先來想想實現思路, 如何能基於dom轉化為圖片? 這塊技術也是老生常談的課題了, 我們都知道可以用canvas來實現, 大致流程如下:
我們如果用原生的實現方案, 大致要經歷以上幾個步驟, 其中第二步是關鍵環節也是最複雜的一步, 我們需要手動實現dom到canvas的映射, 最後轉化為標準的canvas繪圖對象. 當然現成也有很多庫可以直接幫我們簡化這一步驟, 比如html2canvas, dom-to-image. 接下來我們就來解決第一個問題.
在親自調研了html2canvas庫並使用的過程中, 筆者發現了很多問題, 比如如果樣式中出現%單位, 或者有一些圖片背景的問題, 導致html2canvas並沒有很好的work, 而且渲染還原度和清晰度都有問題, 所以筆者暫時沒有深入研究(不過這些問題可以通過修改庫本身解決), 後面筆者直接用了dom-to-image, 發現使用起來很簡單, 而且幾乎不會出現上面說的這些問題, 所以筆者果斷採用了dom-to-image, 後面看了該庫的源碼, 感覺寫的也很優雅易懂, 後期做二次開發應該問題不是很大. 我們可以看看其官網的基本使用:
// 引入import domtoimage from 'dom-to-image';// 生成圖片domtoimage.toPng(node).then(function (dataUrl) { var img = new Image(); img.src = dataUrl; document.body.appendChild(img); }) .catch(function (error) { console.error('oops, something went wrong!', error); });
用法也很簡單,而且它提供了足夠多的配置項,我們可以靈活配置.
第一個問題就這麼解決了, 不過在使用過程中發現圖片模糊的問題, 這塊網上也有很多解決方案. 比如先放大dom, 在處理成canvas最後生成圖片的時候在縮小等, 這塊筆者就不一一舉例了.
因為我們設計的H5頁面都在pc端完成的, 所以要想生成H5預覽圖, 無非是本地模擬尺寸, 進行渲染, 具體方案如下:
採用iframe作為H5頁面容器去生成截圖直接限制寬度在當前頁面生成截圖採用服務端爬蟲一鍵模擬手機訪問生成截圖上面說的方案都可以嘗試,第三種方案筆者之前也開源過爬蟲應用來解決這個問題,感興趣的可以研究了解一下,我們很明顯會選擇第一種方案來實現,就如演示中的,我們看到的彈窗中的H5其實是在iframe中渲染的:
實現思路有了,該問題也就很好實現了,我們只需要在父頁面和iframe實現消息通信即可,比如在iframe加載完成之後手動通知iframe截取自身.基本實現代碼如下:
// 編輯器頁面, 也就是父頁面// 定義截圖子頁面句柄函數window.getFaceUrl = (url) => {setFaceUrl(url) setShowModalIframe(false)}// iframe頁面, 也就是預覽頁面const generateImg = (cb:any) => { domtoimage.toBlob(refImgDom.current, { width, height, } ) .then(function (blob:Blob) { const formData = new FormData(); formData.append('file', blob, 'tpl.jpg'); req.post('/files/upload/free', formData).then((res:any) => { cb && cb(res.url) }) }) .catch(function (error:any) { console.error('oops, something went wrong!', error); });}// 觸發父頁面的方法,將圖片傳給父頁面generateImg((url:string) => { parent.window.getFaceUrl(url);})
最後
以上教程筆者已經集成到H5-Dooring中,對於一些更複雜的交互功能,通過合理的設計也是可以實現的,大家可以自行探索研究。