工作中遇到一个需求:在页面中设置一个提交页面反馈的按钮,用户点击该按钮时在弹出的dialog中可以填写反馈内容,填写完毕点击确定关闭弹窗时捕获当前浏览器窗口中的内容生成图片,用于记录页面中的当前状态,后台将用户填写的内容及生成的图片存入数据库供运维人员查看。经过查阅资料大概的思路分为一下几种:
1、使用java中的Robot类,实现过程如下:
- Robot robot = new Robot();
- robot.delay(10000);
- Dimension d = new Dimension(Toolkit.getDefaultToolkit().getScreenSize());
- int width = (int) d.getWidth();
- int height = (int) d.getHeight();
- //最大化浏览器
- robot.keyRelease(KeyEvent.VK_F11);
- robot.delay(2000);
- Image image = robot.createScreenCapture(new Rectangle(0, 0, width,
- height));
- BufferedImage bi = new BufferedImage(width, height,
- BufferedImage.TYPE_INT_RGB);
- Graphics g = bi.createGraphics();
- g.drawImage(image, 0, 0, width, height, null);
- //保存图片
- ImageIO.write(bi, "jpg", new File("google.jpg"));
该方式经测试后发现在java项目中可以实现当前桌面的截屏,但是用在Web项目中执行至robot.createScreenCapture处就会报错,貌似涉及到权限的问题,而且此方式截屏截到的是服务器端的桌面,毫无疑问被否决了...
2、通过在java程序中通过调用脚本执行第三方的.exe截屏工具实现截图,此实现方式不但涉及并发的问题,而且exe文件在linux系统下能否正常被调用有待考证,所以pass。
3、前两种方式偏向于从后台程序中生成图片的思路,所以更换思路从前台依靠js生成图片,查阅到的资料实现的方式包括dom-to-img、Html2Image、html2canvas等,经过测试前两者在生成图片时格式发生了明显的改变,显然不能满足要求,所以选择采用第三种方式。 html2canvas是一款前端插件,可以实现由dom元素到canvas元素的转换,官方项目github项目地址:点击打开链接。
该插件的使用方式较为简单,引入html2canvas.js文件即可使用,核心方法如下:
html2canvas(domElement, {
option1: *,
option2:*,
......
onrendered: function(canvas){
document.body.appendChild(canvas);
},
});
onrendered: function(canvas){
document.body.appendChild(canvas);
},
});
由于我的前端项目使用vue,所以在package.json文件中引入依赖,引入js文件时需注意:
beta表示为稳定版,发布版,alpha表示测试版,尽量选择稳定版;
然后在需要的页面引入html2canvas,即可使用,我项目中的调用如下:
html2canvas(document.body, {
// allowTaint: true,
taintTest: true,
useCORS: true,
async: false,
// proxy: false,
onrendered: function(canvas) {
var data = canvas.toDataURL('image/png');
...
}
注意:
a、此处生成的data是base64格式的字符串,传到后台需要进行对应的处理生成图片;
b、如果截取的页面中存在跨域图片,需要在后台方法中设置相应的属性。我的项目基springcloud框架,只需添加 @CrossOrign注解即可。
c、附可选的option参数列表:
Name | Type | Default | Description |
---|---|---|---|
allowTaint | boolean | false | 支持跨域 |
background | string | #fff | 背景色,默认透明 |
height | number | null | canvas高度 |
letterRendering | boolean | false | 字间距 |
logging | boolean | false | console.log()输出信息 |
proxy | string | undefined | 加载跨域图片 |
taintTest | boolean | true | 是否在渲染前测试图片 |
timeout | number | 0 | 图片加载延迟,默认延迟为0,单位毫秒 |
width | number | null | canvas宽度 |
useCORS | boolean | false | 支持跨域 |
注:allowTaint与useCORS都是与跨域相关的属性,但是不能同时设置为true,否则会报错;
我查阅很多资料,都是使用allowTaint解决跨域问题的,但是我的项目中使用allowTaint会报禁止跨域请求的问题,使用useCORS可以解决,具体我也不知道什么原因,以后慢慢研究。