以前写过PC浏览器上的html2Canvas,这次是给公司开发钉钉应用,需要在钉钉应用里面上传图片后,并和其他图片、二维码一起,绘制成一个宣传海报。具体步骤见下图:
1.png 2-上传之后.png 3-点击生成海报.png
遇到的问题
1,背景图片模糊问题
- 不需要改插件,所有的图都用img标签,不用background即可解决
2,图片跨域问题
- 后台同事写了一个接口,将oss服务器的图片转换为一个同域下的图片。但是本地测试的时候,仍然有跨域,就使用了base64位做为img的src
3,钉钉中下载图片问题
- 这个项目是vue开发钉钉应用,生成的海报是一个base64位格式。钉钉的api中预览、下载均不支持base64,也不支持blob。所以,
使用了a标签的download属性来下载blob格式的图片(blob://http://192.xxxxxx./xxxxxxx)
4,生成的图片大小与左侧不一致,有空白
- 左侧的imageWrapper区域,是最终绘制的源,要严格设置宽高,不能有空白,否则绘制出来的图也会有空白
5,二维码生成后,无法在微信识别
- 图中二维码大小是55x55,生成的时候,生成200x200或者更大的,但是给二维码的img设置成55x55即可
document.getElementById("j_design_code").innerHTML = '';
let qrDesCode = new QRCode('j_design_code', {
width: 200,
height: 200,
text: 'xxxx', // 二维码内容
render: 'table' // 设置渲染方式(有两种方式 table和canvas,默认是canvas)
});
用到的方法
- 图片转换为base64(img格式:http://xxxxx/xx.png)
getBase64(img){
function getBase64Image(img,width,height) {//width、height调用时传入具体像素值,控制大小 ,不传则默认图像大小
var canvas = document.createElement("canvas");
canvas.width = width ? width : img.width;
canvas.height = height ? height : img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
var dataURL = canvas.toDataURL();
return dataURL;
}
var image = new Image();
image.crossOrigin = 'Anonymous';
image.src = img;
var deferred=$.Deferred();
if(img){
image.onload =function (){
deferred.resolve(getBase64Image(image));//将base64传给done上传处理
}
return deferred.promise();//问题要让onload完成后再return sessionStorage['imgTest']
}
},
- base64转换为blob
base64ToBlob(urlData) {
var arr = urlData.split(',');
var mime = arr[0].match(/:(.*?);/)[1] || 'image/png';
// 去掉url的头,并转化为byte
var bytes = window.atob(arr[1]);
// 处理异常,将ascii码小于0的转换为大于0
var ab = new ArrayBuffer(bytes.length);
// 生成视图(直接针对内存):8位无符号整数,长度1个字节
var ia = new Uint8Array(ab);
for (var i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i);
}
return new Blob([ab], {
type: mime
});
},base64ToBlob(urlData) {
var arr = urlData.split(',');
var mime = arr[0].match(/:(.*?);/)[1] || 'image/png';
// 去掉url的头,并转化为byte
var bytes = window.atob(arr[1]);
// 处理异常,将ascii码小于0的转换为大于0
var ab = new ArrayBuffer(bytes.length);
// 生成视图(直接针对内存):8位无符号整数,长度1个字节
var ia = new Uint8Array(ab);
for (var i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i);
}
return new Blob([ab], {
type: mime
});
},
注意:返回的是 new Blob类型,不能直接用于img的src,需要用
window.URL.createObjectURL(Blob)
转换为blob:http://192.xxxx/xx
详细讲解
- 项目中安装 html2canvas,我的是这个版本
"html2canvas": "^1.0.0-rc.1",
"jquery": "^3.3.1",
- vue页面中引用
import QRCode from 'qrcodejs2' --生成二维码
import $ from 'jquery' --图片转base64的时候用到
import html2canvas from 'html2canvas';
- 上传操作
- 上传是调用后台的接口,将本地图片传到oss服务器,返回给我一个http://xxxxx.png的图片 ,假设赋给变量 noteImg
- 上传成功之后,得到base64位图,做为img的src
uploadSuc{
that.getBase64(that.noteImg)
.then(function (base64) {
that.uploadImgData = base64;
}, function (err) {
console.log(err);
});
}
//html中直接用uploadImgData作为src
<div class="note-main">
<img :src="uploadImgData" alt="">
</div>
- 3,点击‘生成海报’
//生成海报并在右侧预览
previewFun(){
let that = this;
html2canvas(that.$refs.imageWrapper,{
backgroundColor: null,
async: true,
scale:5
}).then((canvas) => {
let dataURL = canvas.toDataURL("image/png");
let tmpBlob = that.base64ToBlob(dataURL);
that.designImgDataURL = window.URL.createObjectURL(tmpBlob);
console.log('预览的海报blob图片 ',that.designImgDataURL);
});
},
//html中代码
<div class="flex-item design-right">
<img class="design-img" :src="designImgDataURL" alt="">
<div style="text-align: right;" v-show="designImgDataURL">
<a :href="designImgDataURL" class="design-download" target="_blank"
:download="designRow.studentName+'.png'">点击下载</a>
</div>
</div>
html结构.png
网友评论