最近在項目中用到了html2canvas插件,遇到的一些坑寫下來,與大家共勉。
html2canvas 官方網站http://html2canvas.hertzen.com/index.html
這是一個js截屏插件,在前台利用h5的canvas 將html的內容顯示在canvas上,再利用 js 將canvas轉化為圖片
1.vue 文件中引入 html2canvas.js
1 <remote-script src="../html2canvas.js"></remote-script>
說明:src中的路徑是html2canvas.js在項目中的路徑
remoteScript 標簽是上篇博客定義的標簽,詳情見:http://www.cnblogs.com/zhuchenglin/p/7455203.html
2.在vue中使用該插件,在methods中定義一個方法,內容為:
1 setTimeout(function () { 2 html2canvas(dom,{ 3 onrendered:function (canvas) { 4 var image = new Image(); 5 image.src = canvas.toDataURL(); 6 document.getElementById('content_img').appendChild(image) 7 dom.style.display='none' 8 }, 9 }); 10 },0)
這樣就可以了
說明:
在方法中如果不加 setTimeout函數的話,雖然使用console輸出的dom內容正常,但是如果在vue中定義的變量中的內容在canvas中顯示不出來,可能與vue的聲明周期有關,這個暫時不清楚,加上setTimeout函數之后,會將此函數中的操作加到處理隊列末尾
在拿到canvas后,轉化為圖片,直接就可以使用了。
3.關於html2canvas截出來的圖片模糊的問題,我查了好多資料,試了好多方法,最終找到一篇非常有用的文章 https://segmentfault.com/a/1190000007707209
方法如下:
(1.修改插件的源碼
<1.代碼第999行renderWindow的方法中修改判斷條件,增加一個options.scale存在的條件:
將
1 if (options.type === "view") { 2 canvas = crop(renderer.canvas, {width: renderer.canvas.width, height: renderer.canvas.height, top: 0, left: 0, x: 0, y: 0}); 3 } else if (node === clonedWindow.document.body || node === clonedWindow.document.documentElement || options.canvas != null) { 4 canvas = renderer.canvas; 5 } else { 6 canvas = crop(renderer.canvas, {width: options.width != null ? options.width : bounds.width, height: options.height != null ? options.height : bounds.height, top: bounds.top, left: bounds.left, x: 0, y: 0}); 7 8 }
修改為
1 if (options.type === "view") { 2 canvas = crop(renderer.canvas, {width: renderer.canvas.width, height: renderer.canvas.height, top: 0, left: 0, x: 0, y: 0}); 3 } else if (node === clonedWindow.document.body || node === clonedWindow.document.documentElement) { 4 canvas = renderer.canvas; 5 }else if(options.scale && options.canvas !=null){ 6 log("放大canvas",options.canvas); 7 var scale = options.scale || 1; 8 canvas = crop(renderer.canvas, {width: bounds.width * scale, height:bounds.height * scale, top: bounds.top *scale, left: bounds.left *scale, x: 0, y: 0}); 9 } 10 else { 11 canvas = crop(renderer.canvas, {width: options.width != null ? options.width : bounds.width, height: options.height != null ? options.height : bounds.height, top: bounds.top, left: bounds.left, x: 0, y: 0}); 12 }
2.代碼第 943 行 html2canvas 的方法中 修改width,height:
將
1 return renderDocument(node.ownerDocument, options, node.ownerDocument.defaultView.innerWidth, node.ownerDocument.defaultView.innerHeight, index).then(function(canvas) { 2 if (typeof(options.onrendered) === "function") { 3 log("options.onrendered is deprecated, html2canvas returns a Promise containing the canvas"); 4 options.onrendered(canvas); 5 } 6 return canvas; 7 });
改為:
1 width = options.width != null ? options.width : node.ownerDocument.defaultView.innerWidth; 2 height = options.height != null ? options.height : node.ownerDocument.defaultView.innerHeight; 3 return renderDocument(node.ownerDocument, options, width, height, index).then(function(canvas) { 4 if (typeof(options.onrendered) === "function") { 5 log("options.onrendered is deprecated, html2canvas returns a Promise containing the canvas"); 6 options.onrendered(canvas); 7 } 8 return canvas; 9 });
然后就可以使用了,將原來的使用放式稍微還一下就可以了,使用實例如下:
在vue的方法中添加一個獲取設備像素密度的方法
1 getPixelRatio(context){ 2 var backingStore = context.backingStorePixelRatio || 3 context.webkitBackingStorePixelRatio || 4 context.mozBackingStorePixelRatio || 5 context.msBackingStorePixelRatio || 6 context.oBackingStorePixelRatio || 7 context.backingStorePixelRatio || 1; 8 return (window.devicePixelRatio || 1) / backingStore; 9 },
然后將最上面的使用示例改為:
1 get_img(){ 2 let self = this; 3 setTimeout(function () { 4 var content_html = document.getElementById('content_html'); //要轉化的div 5 let width = content_html.offsetWidth; 6 let height = content_html.offsetHeight; 7 let offsetTop = content_html.offsetTop; 8 let canvas = document.createElement("canvas"); 9 let context = canvas.getContext('2d'); 10 let scaleBy = self.getPixelRatio(context); 11 canvas.width = width*scaleBy; 12 canvas.height = (height+offsetTop)*scaleBy; 13 context.scale(scaleBy,scaleBy); 14 var opts = { 15 allowTaint:true,//允許加載跨域的圖片 16 tainttest:true, //檢測每張圖片都已經加載完成 17 scale:scaleBy, // 添加的scale 參數 18 canvas:canvas, //自定義 canvas 19 logging: true, //日志開關,發布的時候記得改成false 20 width:width, //dom 原始寬度 21 height:height //dom 原始高度 22 }; 23 html2canvas(content_html,opts).then(function (canvas) { 24 canvas.style.width = width+"px"; 25 canvas.style.height = height+"px"; 26 var image = new Image(); 27 image.src = canvas.toDataURL(); 28 document.getElementById('content_img').appendChild(image); //將轉化好的圖片插入到防止圖片轉換的div中 29 content_html.style.display='none' 30 }); 31 }
然后在html2canvas插件加載成功后調用get_img()方法即可將比較清晰的圖片插入到指定位置
注:如需轉載請注明出處:http://www.cnblogs.com/zhuchenglin/p/7455336.html