以前寫過PC瀏覽器上的html2Canvas,這次是給公司開發(fā)釘釘應(yīng)用,需要在釘釘應(yīng)用里面上傳圖片后,并和其他圖片、二維碼一起,繪制成一個(gè)宣傳海報(bào)。具體步驟見下圖:

1.png

2-上傳之后.png

3-點(diǎn)擊生成海報(bào).png
遇到的問題
1,背景圖片模糊問題
- 不需要改插件,所有的圖都用img標(biāo)簽,不用background即可解決
2,圖片跨域問題
- 后臺(tái)同事寫了一個(gè)接口,將oss服務(wù)器的圖片轉(zhuǎn)換為一個(gè)同域下的圖片。但是本地測(cè)試的時(shí)候,仍然有跨域,就使用了base64位做為img的src
3,釘釘中下載圖片問題
- 這個(gè)項(xiàng)目是vue開發(fā)釘釘應(yīng)用,生成的海報(bào)是一個(gè)base64位格式。釘釘?shù)腶pi中預(yù)覽、下載均不支持base64,也不支持blob。所以,
使用了a標(biāo)簽的download屬性來下載blob格式的圖片(blob://http://192.xxxxxx./xxxxxxx)
4,生成的圖片大小與左側(cè)不一致,有空白
- 左側(cè)的imageWrapper區(qū)域,是最終繪制的源,要嚴(yán)格設(shè)置寬高,不能有空白,否則繪制出來的圖也會(huì)有空白
5,二維碼生成后,無法在微信識(shí)別
- 圖中二維碼大小是55x55,生成的時(shí)候,生成200x200或者更大的,但是給二維碼的img設(shè)置成55x55即可
document.getElementById("j_design_code").innerHTML = '';
let qrDesCode = new QRCode('j_design_code', {
width: 200,
height: 200,
text: 'xxxx', // 二維碼內(nèi)容
render: 'table' // 設(shè)置渲染方式(有兩種方式 table和canvas,默認(rèn)是canvas)
});
用到的方法
- 圖片轉(zhuǎn)換為base64(img格式:http://xxxxx/xx.png)
getBase64(img){
function getBase64Image(img,width,height) {//width、height調(diào)用時(shí)傳入具體像素值,控制大小 ,不傳則默認(rèn)圖像大小
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轉(zhuǎn)換為blob
base64ToBlob(urlData) {
var arr = urlData.split(',');
var mime = arr[0].match(/:(.*?);/)[1] || 'image/png';
// 去掉url的頭,并轉(zhuǎn)化為byte
var bytes = window.atob(arr[1]);
// 處理異常,將ascii碼小于0的轉(zhuǎn)換為大于0
var ab = new ArrayBuffer(bytes.length);
// 生成視圖(直接針對(duì)內(nèi)存):8位無符號(hào)整數(shù),長(zhǎng)度1個(gè)字節(jié)
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的頭,并轉(zhuǎn)化為byte
var bytes = window.atob(arr[1]);
// 處理異常,將ascii碼小于0的轉(zhuǎn)換為大于0
var ab = new ArrayBuffer(bytes.length);
// 生成視圖(直接針對(duì)內(nèi)存):8位無符號(hào)整數(shù),長(zhǎng)度1個(gè)字節(jié)
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)轉(zhuǎn)換為blob:http://192.xxxx/xx
詳細(xì)講解
- 項(xiàng)目中安裝 html2canvas,我的是這個(gè)版本
"html2canvas": "^1.0.0-rc.1",
"jquery": "^3.3.1",
- vue頁面中引用
import QRCode from 'qrcodejs2' --生成二維碼
import $ from 'jquery' --圖片轉(zhuǎn)base64的時(shí)候用到
import html2canvas from 'html2canvas';
- 上傳操作
- 上傳是調(diào)用后臺(tái)的接口,將本地圖片傳到oss服務(wù)器,返回給我一個(gè)http://xxxxx.png的圖片 ,假設(shè)賦給變量 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,點(diǎn)擊‘生成海報(bào)’
//生成海報(bào)并在右側(cè)預(yù)覽
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('預(yù)覽的海報(bào)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'">點(diǎn)擊下載</a>
</div>
</div>

html結(jié)構(gòu).png