需求:將html表格導出為圖片,表格可以自己編輯數據,並適配各種屏幕大小。上網搜了下,找到了html2canvas,一開始使用的是最新版0.5.0,最終因為需要支持自定義div編輯框自動換行選擇了v0.4.1 - 7.9.2013。
開始編輯框使用的是textarea,后來發現textarea不能自適應高度,內容一多就會出現滾動條。這對於要把表格轉化成圖片的需求來說是沒法接受的,於是改為了
div{ word-wrap: break-word; }
<div contenteditable="true"></div>
於是第一個坑出現了,html2canvas0.5不識別‘word-wrap: break-word;' ,內容一多就直接超出了編輯框。。。
google后發現0.4版本支持‘word-wrap: break-word;' ,我也是醉了。當然新版本還是有進步的,比如就不會出現這個問題:IE下border為1px時不顯示。
解決方案:
改動0.4版本源代碼:
function getCSSInt(element, attribute) { //var val = parseInt(getCSS(element, attribute), 10); /** * my-change liyimin */ var val = parseFloat(getCSS(element, attribute), 10); /** * my-change end */ return (isNaN(val)) ? 0 : val; // borders in old IE are throwing 'medium' for demo.html }
其實上面都是小坑,真正的大坑是html2canvas默認以屏幕的寬為canvas的寬,當需要轉化的html超出屏幕范圍時就只能轉化當前可視部分,
一開始使用0.5版本的時候也找到了一個解決方案,焰尾迭的 使用html2canvas實現瀏覽器截圖
// return renderDocument(node.ownerDocument, options, node.ownerDocument.defaultView.innerWidth, node.ownerDocument.defaultView.innerHeight, index).then(function(canvas) { // if (typeof(options.onrendered) === "function") { // log("options.onrendered is deprecated, html2canvas returns a Promise containing the canvas"); // options.onrendered(canvas); // } // return canvas; // }); /** *my-change liyimin */ var width = options.width != null ? options.width : window.innerWidth; var height = options.height != null ? options.height : window.innerHeight; return renderDocument(node.ownerDocument, options, width, height, index).then(function(canvas) { if (typeof(options.onrendered) === "function") { log("options.onrendered is deprecated, html2canvas returns a Promise containing the canvas"); options.onrendered(canvas); } return canvas; }); /** *my-change end */
但是實際使用的時候也是各種問題。比如width和height設大了,渲染出來的canvas總是各種空白部分,設得和需要轉化的html一樣大又有可能渲染不全,無奈放棄。
查找了兩三天終於找到了一個解決方案,就快要放棄了啊。
解決當內容超出屏幕范圍無法全部截取問題:
<div> <iframe id="previewIframe" src="/static/html/preview.html" frameborder="0"></iframe> </div>
將需要轉化的html放在preview.html里面,超出多少都無所謂了有木有啊。
最終就是這樣:
var $previewIframe=$('#previewIframe'); html2canvas($previewIframe.contents().find('#previewTabelDetail')[0], { onrendered: function(canvas) { var url = canvas.toDataURL(); $previewIframe.contents().find('body').append($(<img>").attr("src", url)); } });
本來是打算直接下載圖片的,這樣:
var $previewIframe=$('#previewIframe'); html2canvas($previewIframe.contents().find('#previewTabelDetail')[0], { onrendered: function(canvas) { var triggerDownload = $("<a>").attr("href", url).attr("download", "表格.png").appendTo("body"); triggerDownload[0].click(); triggerDownload.remove(); } });
可惜安卓上不支持直接下載base64的圖片鏈接,就改為生成圖片讓用戶自己手動保存。
補充:
其實關於超出屏幕范圍的截圖沒那么麻煩,根本不需要使用iframe,html2canvas之所以獲取不到超出部分是因為對象element的父元素寬高不夠,也就是說只要將父元素的寬高設為和需要轉換為canvas的子元素的寬高一樣大就不會出現這個問題啦