使⽤html2canvas.js 实现页⾯截图并显⽰或上传
最近写项⽬有⽤到html2canvas.js ,可以实现页⾯的截图功能,但遭遇了许多的坑,特此写⼀篇随笔记录⼀下。
在使⽤html2canvas 时可能会遇到诸如只能截取可视化界⾯、截图没有背景⾊、svg 标签⽆法截取等问题,下⾯详细的说明⼀下。⼀、导⼊html2canvas.js
也可以直接导⼊链接:
使⽤起来也⾮常简单,具体的API 可以去⽹上查,⽣成png 图⽚使⽤“image/png”即可。
其中$("#xxx")为你想要截取的div ,外⾯可以通过jquery 获取它,当然document 获取也是可以的。
其它类型的图⽚如jpg ,为image/jpeg 等等,可⾃⾏查询API 。
到这⾥其实简单的截图已经完成了,如果界⾯稍微复杂⼀点的话,可能就会出现各种坑,下⾯⼀个⼀个解决。
⼆、svg ⽆法截取的问题
当我们截取⼀个div 时,如果这个div 中存在svg 标签,⼀般情况下是截取不到的,⽐如截取⼀个流程图,得到的是下⾯这个样⼦:
可以看到,流程图的线没有截取到,也就是svg 没有截取到,这时的解决⽅法是把svg 转换成canvas 再进⾏截图即可,直接上代码。 这⾥的each 循环是循环所有的svg 标签,将它们全部转换为canvas
<script src="cdn.bootcss/html2canvas/0.5.0-beta4/html2canvas.js"></script>html2canvas($("#xxx"), {
onrendered: function (canvas) {
var url = DataURL("image/png");
window.location.href = url;
svg canvas}
});
if (typeof html2canvas !== 'undefined') {
/
/以下是对svg 的处理
var nodesToRecover = [];
var nodesToRemove = [];
var svgElem = cloneDom.find('svg');
svgElem.each(function (index, node) {
var parentNode = node.parentNode;
var svg = im();
var canvas = ateElement('canvas');
canvas.width = 650;
canvas.height = 798;
canvg(canvas, svg);
if (node.style.position) {
canvas.style.position += node.style.position;
canvas.style.left += node.style.left;
p += p;
}
nodesToRecover.push({
parent: parentNode,
child: node
});
nodesToRemove.push({
parent: parentNode,
child: canvas
});
parentNode.appendChild(canvas);
});
}
这⾥需要⽤到canvg.js,以及它的依赖⽂件rgbcolor.js,⽹上可以直接下载,也可以直接导⼊。
三、背景透明的问题
这个其实很简单,因为它默认是透明的,html2canvas中有⼀个参数background就可以添加背景⾊,如下:
html2canvas(cloneDom, {
onrendered: function(canvas) {
var url =DataURL("image/png");
},
background:"#fafafa"
});
四、只能截取可视部分的问题
如果需要截取的div超出了界⾯,可能会遇到截取不全的问题,如上图,只有⼀半的内容,这是因为看不到的部分被隐藏了,⽽html2canvas是⽆法截取隐藏的dom的。
所以此时的解决办法是使⽤克隆,将需要截取的部分克隆⼀份放在页⾯底层,再使⽤html2canvas截取这个完整的div,截取完成后再remove这部分内容即可,完整代码如下:
function showQRCode() {
scrollTo(0, 0);
//克隆节点,默认为false,即不复制⽅法属性,为true是全部复制。
var cloneDom = $("#d1").clone(true);
//设置克隆节点的z-index属性,只要⽐被克隆的节点层级低即可。
cloneDom.css({
"background-color": "#fafafa",
"position": "absolute",
"top": "0px",
"z-index": "-1",
"height": 798,
"width": 650
});
if (typeof html2canvas !== 'undefined') {
/
/以下是对svg的处理
var nodesToRecover = [];
var nodesToRemove = [];
var svgElem = cloneDom.find('svg');//divReport为需要截取成图⽚的dom的id
svgElem.each(function (index, node) {
var parentNode = node.parentNode;
var svg = im();
var canvas = ateElement('canvas');
canvas.width = 650;
canvas.height = 798;
canvg(canvas, svg);
if (node.style.position) {
canvas.style.position += node.style.position;
这⾥外⾯⾸先将要截取的div 克隆⼀份,并将z-index 设置为最⼩,避免引起界⾯的不美观,然后是对svg 进⾏的处理,上⾯已经分析过了,最后将克隆节点追加到body 后⾯即可。 在onrendered 中,我们可以直接使⽤location.href 跳转查看图⽚,可以进⾏保存操作,也可以将url 写⼊img 的src 中显⽰在界⾯上,如
最后可以在界⾯展⽰刚刚截取到的图⽚:
五、上传图⽚保存到数据库,并在界⾯中获取该图⽚显⽰
现在得到url 了,需要上传到后端,并存到数据库中,再另⼀个展⽰的界⾯中加载该图⽚。我⼀般习惯于使⽤url 来存储图⽚路径,⽽不是⽤blob 存储。
因为需要在另⼀个界⾯中获取图⽚,所以我把图⽚存在了与webapp 同级的⼀个resource ⽬录下,代码如下:
这⾥因为涉及到其它逻辑,所以只放⼀部分代码。
这⾥使⽤的是BASE64Decoder 来存储图⽚,我们获取到图⽚后,需要使⽤substring 将“data:image/png;base64,”的内容截取掉,因为“,”后⾯才是图⽚的url , 。
对于路径,上⾯代码中的url 是我存储到数据库中的内容,⽽totalUrl 就是实际进⾏ImageIO 的write 操作时存储的真实路径,getProperty()⽅法获取的项⽬的根⽬录,可以在l 中配置如下内容,然后 即可。
canvas.style.left += node.style.left;
p += p;
}
nodesToRecover.push({
parent: parentNode,
child: node
});
nodesToRemove.push({
parent: parentNode,
child: canvas
});
parentNode.appendChild(canvas);
});
//将克隆节点动态追加到body 后⾯。
$("body").append(cloneDom);
html2canvas(cloneDom, {
onrendered: function (canvas) {
var url =DataURL("image/png");
window.location.href = url ;
},
background:"#fafafa"
});
}
}
$('#imgId').attr('src',url); //存储图⽚并返回图⽚路径
BASE64Decoder decoder = new BASE64Decoder();
byte [] b = decoder.ProPic().substring("data:image/png;base64,".length()));
ByteArrayInputStream bais = new ByteArrayInputStream(b);
BufferedImage bi1 = ad(bais);
String url = "user_resource" + File.separator + "img" + File.separator + "product_"+UUID.randomUUID().toString().replace("-", "")+".png";
String totalUrl = Property("root") + url;
File w2 = new File(totalUrl);
ImageIO.write(bi1, "png", w2);
product.setProPic(url); //将图⽚的相对路径存储到数据库中
int res = productMapper.insertSelective(product); //添加到数据库
url.substring("data:image/png;base64,".length())Property("root")
现在图⽚的url 就存到数据库⾥了,⽽图⽚本⾝就存储在tomcat 下该项⽬的这个⽬录下。 最后外⾯在界⾯上获取,只需要在当前的url 前⾯加上项⽬名即可 。
然后就可以看到界⾯上显⽰的图⽚了:
<!-- 配置系统获得项⽬根⽬录 -->
<context-param >
<param-name >webAppRootKey </param-name >
<param-value >root </param-value >
</context-param >
<listener >
<listener-class >
org.springframework.web.util.WebAppRootListener
</listener-class >
</listener >
<img class ="depot-img" src ="<%=ContextPath()%>/`+e.proPic+`">
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论