html2canvas插件(官网地址):
html2canvas插件相当于把相应的DOM节点里的所有元素按其属性来构建,然后生成截图保存,有些css属性它无法识别(理解不了),所以产生会有点偏差,不过问题不大
浏览器兼容:
- Firefox 3.5+
- Google Chrome
- Opera 12+
- IE9 +
- Edge
- Safari 6+
安装及引入:
npm install html2canvas
# document即是需要绘制的节点,option为一些可配置的选项
import html2canvas from 'html2canvas'
html2canvas(document,option).then(canvas=>{......})
option部分可用参数:
参数名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
allowTaint | boolean | false | 是否允许跨域 |
background | string | #ffffff | 画布的背景色,如果没有在DOM中指定,将设置为透明 |
canvas | document | null | 现有canvas元素用作绘图的基础 |
imageTimeout | number | 15000 | 加载图像的超时时间(单位: 毫秒),设置为0为禁用超时 |
timeout | number | 0 | 图片加载延时,默认延时为0(单位: 毫秒) |
logging | boolean | true | 在console.log()输出以进行调试 |
proxy | string | undefined | 设置跨域代理地址,如果留空则不会加载跨域图像 |
taintTest | boolean | true | 是否在渲染前测试图片 |
useCORS | boolean | false | 是否尝试使用CORS从服务器加载图像(也是跨域图像,我使用的时候未成功,原因未知) |
width | number | null | 画布宽度 |
width | height | null | 画布高度 |
如果要从渲染中排除某些elements,则可以向这些元素添加data-html2canvas-ignore属性,html2cnavas会将它们从渲染中排除
上各种代码:
需要转化成图片的节点统统放在imageWrapper节点里,在节点外的元素不会被一起生成海报,所以上面那个ignore也可以不要,看业务场景吧;之后把整个画布铺满页面,层级设置最高,透明度设置为0, 就可以实现长按保存啦!
//Share.vue --- html
<div class="share">
<div class="imageWrapper" ref="imageWrapper">
<img class="real_pic" :src="dataURL" />
<!-- 需要转化为图片的DOM元素 -->
<slot>
<div class="canvas-bg">
<img class="canvas-title" src="@/images/canvas-title.png" alt />
<div class="canvas-info">
<div class="info-content">
<span>我叫</span>
<span>{{ userInfo.name }}</span>
</div>
<div class="info-content">
<span>来自</span>
<span>{{ userInfo.userSchool }}</span>
</div>
<div class="info-content">在****大学</div>
<div class="info-content">
<span>学习</span>
<span class="study-day">{{ userInfo.study_day }}</span>
<span>天啦</span>
</div>
</div>
<div class="canvas-footer">
<div class="canvas-user">
<img :src="userInfo.user_image" alt />
</div>
</div>
<div class="canvas-er">
<img :src="userInfo.share_qrcode" alt />
<div class="text">长按保存图片</div>
<div class="text">扫码一起学习</div>
</div>
</div>
</slot>
</div>
<div class="watermark">长按海报保存图片</div>
</div>
在mounted的时候调用生成即可,图片加载有时候比较慢,最好在外面加个延时器
//Share.vue --- js
html2canvas(){
setTimeout(() => {
html2canvas(this.$refs.imageWrapper, {
backgroundColor: null, //解决生成会有白边的可能,但是没有遇到有白边,不知道有没有生效
allowTaint: true, //是否允许跨域图片(官方文档,代试验)
useCORS: true,
taintTest: true
})
.then(canvas => {
// this.$refs.imageWrapper.appendChild(canvas)
let dataURL = canvas.toDataURL("image/png");
this.dataURL = dataURL;
this.ready(dataURL);
})
}, 1000);
}
问题总结
- 一开始使用跨域的图片, 生成的海报有时候没有相应的图片, 所以把图片统一转成了base64格式的, 如果没有跨域问题,不用转换感觉更好
/*
** len -- 图片的宽高,因为我的图片宽高都一样,所以直接一个参数即可
** url -- 图片路径
*/
getUrlBase64_pro(len,url) {
//网络资源图片转成base64
// console.log("图片路径",url)
var canvas = document.createElement("canvas"); //创建canvas DOM元素
var ctx = canvas.getContext("2d");
return new Promise((reslove, reject) => {
var img = new Image();
img.crossOrigin = "Anonymous";
img.onload = function() {
canvas.height = len; //指定画板的高度,自定义
canvas.width = len; //指定画板的宽度,自定义
ctx.drawImage(img, 0, 0, len, len); //参数可自定义
var dataURL = canvas.toDataURL("image/");
canvas = null;
reslove(dataURL);
};
img.onerror = function(err){
reject(err)
}
img.src = url;
});
}
因为有多张图片,我这边直接搞成一个promise,后面就通过Promise.all来同步转换多张图片,之后再生成海报.一次转换,终身受益.
- 部分安卓手机生成的海报图片会有一条线,IOS却没有,本来以为是切的图的问题,后来换了图也不行,不知道是兼容性问题还是我的样式有问题.