vue中使用html2canvas及解决html2canvas截屏图片模糊问题

最近在项目中用到了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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏前端布道

JavaScript实现简单的双向数据绑定

双向数据绑定简单来说就是UI视图(View)与数据(Model)相互绑定在一起,当数据改变之后相应的UI视图也同步改变。反之,当UI视图改变之后相应的数据也同步...

13130
来自专栏小程序之家

如何在小程序中使用地图

这篇文章中,我们将介绍小程序地图组件的使用,官方文档已经比较详细的介绍了map组件的使用,但是对于刚开始接触地图组件的同学,难免有些难以下手。本文将以Hello...

1.7K40
来自专栏张善友的专栏

Notepad2 一个很不错的记事本

有如下特性: 1、自定义语法高亮,支持HTML, XML, CSS, JavaScript, VBScript, ASP,PHP, CSS, Perl/CGI,...

26790
来自专栏WindCoder

Angular6自定义表单控件方式集成Editormd

曾经找到过“Editor.md”,看之心喜,一直想在Angular中集成下这款markdownpad编辑器玩,在网上也只找到一篇通过指令集成的,虽然可以实现,但...

57720
来自专栏Hellovass 的博客

关于 Vue 响应式原理的困惑

需要将用户信息的 UI(下文用 UserInfo 来代替) 写成一个 Vue 组件,达到重用的目的。

31340
来自专栏web前端教室

[每周日-先行者课堂笔记] -- react版的倒计时实现

image.png 各位同学们大家好,今天是4月9号周日,今天我们继续来做“倒计时”这个前端组件。之前我们是使用原生js来实现的,其实更多的只是实现了功能。 这...

40370
来自专栏小樱的经验随笔

【亲测有效】Nodepad++/Sublime Text3中Python脚本运行出现语法错误:IndentationError: unindent does not match any outer i

我在开发游戏的时候,发现一个python脚本,本来都运行好好的,然后写了几行代码,而且也都确保每行都对齐了,但是运行的时候,却出现语法错误:  Indentat...

33250
来自专栏有趣的django

微信小程序入门(三)

四个组成部分,其它三个前面介绍过了,主要WXS: WXS:对wxml增强的一种脚本语言,可以对请求的数据进行filter或者做计算处理,帮助wxml快速构建出...

18540
来自专栏用户2442861的专栏

Qt学习——分割窗口QSplitter类 .

1.建立项目时基类选择QMainWindow,取消Gernerate form复选框的选中状态。

14210
来自专栏葡萄城控件技术团队

基于jQuery UI CSS Framework开发Widget

jQuery UI CSS Framework是jQuery UI中的一个样式框架,可以利用jQuery Theme roller 来生成自己想要的css样式效...

229100

扫码关注云+社区

领取腾讯云代金券