一、前言
我发现将DOM转化为图片是一个非常常见的需求,而自己手动转是非常麻烦的,于是找到了html2canvas这个插件,既是用得比较多的也是维护得比较好的一个插件。
二、代码
1.安装
npm install html2canvas --save
现在最新的版本应该是1.0.0,另外还有一个比较经典的版本是0.5.0,网上有许多关于这个版本的bug说明。
2.使用
1 | <img class="real_pic" :src="dataURL" /> |
imageWrapper里面是你需要转化为图片的DOM元素。
1 | data() { |
dataURL是最后转化出来的图片base64地址,放在img标签中即可展示。
1 | methods: { |
html2canvas的用法非常简单,不过1.0.0已经将写法改为了promise,在.then
方法里获取canvas对象。
常见bug
1.生成出来的图片有白色边框
在配置项里配置backgroundColor: null
即可,如果对图片宽度有要求,设置width。
1 | this.$nextTick(() => { |
2.有图片显示不出来并有报错(一般是跨域的错)
这是最常见的一个bug,就是这个插件无法生成跨域了的图片,也看了官方文档配置了也百度了都没有好的办法,最后是让后端直接把跨域的图片转成base64,就完美解决了这个问题。不过图片转换成base64加增加图片文件大小,如果图片比较大,不建议转换base64,否则会增加网页加载时间,影响网站速度,这种方式一般适用于小图。
3.生成图片后会在原始DOM上覆盖而产生一个闪动的效果
先让生成的图片隐藏,等生成好以后再展示。(没有在手机上测试,效果不一定令人满意)
4.经典版本(0.5.0)常见bug
4.1.生成的图片模糊
4.2.有跨域图片导致生成的图片不完整
这两个问题网上百度都有很多解决办法。
5.html2canvas转换的base64位图不能被ios8以上版本所识别。
采用了另一款插件,dom-to-image,弄上去没有问题了。
dom-to-image运用上去,在ios上能够出现内容了,但发现存在一个问题,部分图片内容,第一次进行公众号网页加载,没有正确显示,要在次进入才会显示,此bug同样是ios8以上版本,运用dom-to-imagede toSvg方式完美解决问题。
html2canvas动态加载内容,通过canvas转换出来的数据,图片为空
问题分析:
内容是动态加载进来的,转换肯定是在请求完毕之后再去转换,但是在请求完毕之后去转换,按理说所需要的所有数据都已经到达前端,应该可以转换,经过思考,发现图片内容从后台读取需要一定时间去解析,才能够完整的将图片资源展示出来,html2canvas是将页面上显示的dom元素,经过解析将dom画在canvas上在转换为image图片格式。
解决办法:
1.让html2canvas转换代码等待一定时间,在进行转换操作,可进行转换。代码如下图所示
2.当全部的图片数据都加载完毕之后,在执行转换操作。(本人建议第二种,更保险)
vue中完美解决html2canvas图片跨域问题
html2canvas在截图的过程中,如果遇到html中有跨域地址的图片,比如图片存在了别人的云上,截图的时候将不会显示图片,解决方案如下:
1 | import html2canvas from 'html2canvas' |
html代码
1 | <div class="share-wrap" ref="screenshot"> |
这里有几个关键的地方:
allowTaint: true
和useCORS: true
都是解决跨域问题的方式,不同的是使用allowTaint 会对canvas造成污染,导致无法使用canvas.toDataURL
方法,所以这里不能使用allowTaint: true
- 在跨域的图片里设置
crossOrigin="anonymous"
并且需要给imageUrl加上随机数 canvas.toDataURL('image/jpg')
是将canvas转成base64图片格式。
注意:前端设置了 crossOrigin="anonymous"
,还需要后端配合,即请求图片返回的响应头中带有Access-Control-Allow-Origin
且值为*
,(允许所有网站跨域请求)或者当前网站域名(只允许固定域名下跨域请求)。
1 | location ~ ^/public/.*\.(jpg|png|jpeg) { |
扩展阅读:
JS - 使用 html2canvas 将页面保存成图片
html2canvas以及domtoimage的使用踩坑总结
解锁canvas导出图片跨域的N种姿势~