需求:将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的子元素的宽高一样大就不会出现这个问题啦