// 閱讀須知:因為我是在描述我從頭開始做這個批量打包的一個思路,也就是思考歷程,所以大家在閱讀過后可能會覺得邏輯有點反,為什么要把繪制放到最后面,我是希望能夠幫大家分享一下我的分析思路,僅供參考。
一、插件安裝
首先是插件的安裝與引入,這里我們用的是qrcode的這個插件,直接使用npm install qrcodejs2安裝即可,但是這里要注意,如果你用的是ts進行開發的話,這時候用傳統的import將qrcode引進來是不可取的,他會報錯:TS7016: Could not find a declaration file for module 'qrcodejs2'. '/node_modules/qrcodejs2/qrcode.js' implicitly has an 'any' type. Try `npm install @types/qrcodejs2` if it exists or add a new declaration (.d.ts) file containing `declare module 'qrcodejs2';`。這里為什么會出現這個問題,我暫不知道,知道的同學們歡迎留言。不過解決方案的話,我們可以參考這個博客:https://blog.csdn.net/mhbsoft/article/details/92842278,這里博客里面已經說得很詳細了。
二、二維碼生成
接下來就是插件的使用了,qrcode這個插件的使用,總體來說還是很簡單的,它主要是通過獲取dom元素,然后通過HTML5 cavans繪制而成的。首先我們需要在html里定義一個放置二維碼的dom元素,
<div id="qrcode"> </div>
然后定義一個方法
qrcode(){
let qrcode = new this.QRCode('qrcode', {
width: 272, //圖像寬度
height: 272, //圖像高度
colorDark: "#000000", //前景色
colorLight: "#ffffff", //背景色
typeNumber: 4, correctLevel: this.QRCode.CorrectLevel.H //容錯級別 容錯級別有:(1)QRCode.CorrectLevel.L (2)QRCode.CorrectLevel.M (3)QRCode.CorrectLevel.Q (4)QRCode.CorrectLevel.H })
qrcode.clear(); //清除二維碼
qrcode.makeCode(this.data.url);//生成另一個新的二維碼
}
然后在mouted里面調用這個方法,但是有的項目的mouted不起作用,我們還可以這樣,
created(){ this.$nextTick(()=>{ // $nextTick是指在頁面dom元素都加載完了之后再執行里面的方法,從而也起到了一個mouted的作用。 this.qrcode(); }) }
以上就是我們生成二維碼的全過程了。
三、二維碼打包以及導出
二維碼已經生成好了,接下來就是打包了,打包的話這里用到了兩個插件,分別是jsZIP以及FileSaver,這兩個一個是將文件整合成壓縮包一個是生成對應的文件目錄,引入方法和上面引入qrcode是一樣的。接下來我們來看下這個打包方法的實現:
function downImg(imgArr,title) { // imgArr是我們要下載的圖片列表,title就是你下載出來的壓縮包的名稱 var zip = new JSZip(); var file_name = ''; for(let i=0;i<imgArr.length;i++) { // 循環我們傳進來的圖片列表,為每一張圖片賦值 let item = imgArr[i].img let name = imgArr[i].hospital+imgArr[i].department+ imgArr[i].name; // 每一張圖片的名字,可以根據自己的規則生成 file_name = title + '.zip'; // 生成的文件的名字 var img = zip.folder(name); // 生成壓縮圖片 var img_arr = item.split(','); img.file(name + '.png', img_arr[1], {base64: true}); // 生成圖片,采用base64格式 } ·zip.generateAsync({type:"blob"}).then(function(content) { ·FileSaver.saveAs(content, file_name); // 生成文件,調用saveAs ·}); }
從上面的代碼我們可以看出,我們需要將我們要導出的圖片的base64地址拿到,然后才可以調用這個方法,於是接下來我們看怎么將圖片轉成base64格式。
四、繪制我們需要的圖片格式
一般情況下,我們繪制圖片的話,直接用cavans將我們需要繪制的dom元素給轉成圖片,代碼如下:
html2canvas(Dom,{ // Dom就是我們要轉成圖片的頁面節點,可以通過id選擇器、類選擇器或者refs獲取 backgroundColor: null }).then((canvas) => { let dataURL = canvas.toDataURL("image/png"); // 這里調用cavans的toDataURL方法來獲取轉化后的base64格式的路徑 this.dataURL = dataURL; // 賦值出去,這里拿到的dataURL的地址就是一個base64格式的地址了,我們可以用它來直接繪制圖片 });
但是,經過我的檢測,發現在vue+ts的項目中,他會報錯html2cavans這個方法找不到,應該是沒有定義這個方法,畢竟ts和js的區別就是ts必須有明確的定義,但是我沒有找到有效的聲明方法,所以我采用了下面的第二種方法
drawImg(){ // 定義一個方法,來繪制我們要導出的二維碼var canvas=document.createElement("canvas"); // 創建一個cavans元素 canvas.width = 510; // 定義cavans寬高,也是我們導出的圖片的寬高 canvas.height = 700; var ctx=canvas.getContext("2d")!; // 定義一個變量來進行cavans的二維繪制 var img= new Image(); // 新建一個圖片元素 // 給圖片賦值,一般這里是要放絕對路徑的,如果找不到絕對路徑的話,可以用require的方式來定義,let bgImg = require('../assets/image/bg.png')
img.src = bgImg; img.onload = ()=>{ // 這里之所以用onload,是要等圖片繪制完成了再干其他的事情,否則的話可能出現最后導出的圖片沒有背景圖的情況,因為繪制圖片相當於一個異步的過程,踩坑踩坑 ctx.drawImage(img,10,10); // 繪制圖片,里面的后兩個參數是坐標
ctx.fillStyle="#ffffff"; // 設置填充色,為下面的矩形 ctx.fillRect(114,240,276,276); // 繪制一個矩形,前兩個參數是坐標,后兩個參數是矩形的寬高 let img2 = new Image(); // 下面我們該將二維碼繪制上去了,首先因為二維碼是我們借助qrcode生成的,所以我們需要獲取到生成的二維碼的src,但是我暫時還沒有找到方法獲取qrcode生成的二維碼的路徑,所以只能采用下方的這種方式,因為qrcode其實已經將生成的二維碼繪制到頁面上指定的標簽里面了,
// 所以我們可以通過去尋找生成的img元素,並且通過cas.toDataURL的方法去獲取相應的路徑。 let cas:any = document.querySelector('#qrcode')!.children[this.index*2]; var data1 = cas.toDataURL('image/jpg'); img2.src = data1; img2.onload = ()=>{ // 這里同樣是避免異步 ctx.drawImage(img2,115,242);
ctx.font="30px PingFangSC-Semibold"; // 這里是繪制文字 ctx.fillStyle = '#1C3063'; // 文字顏色 ctx.textAlign='center'; // 設置文字的位置,居中還是左右對齊,居中對齊的中心位置就是下面設置的坐標,同理,左右對齊的相對位置也是以下方的坐標為准的 ctx.fillText(this.data.name!+' '+this.data.position!,255,600); // 設置文字的內容,第一個參數是文字容,第二三個參數是坐標
let dependce = this.data.hospital!+' '+this.data.department!; if(dependce){ // 這里是做了一個如果文字超過18個字,就開始換行,並且仍舊是居中對齊 if(dependce.length >10){ ctx.font="26px PingFangSC-Semibold"; ctx.fillStyle = '#1C3063'; ctx.textAlign='center'; ctx.fillText(dependce.slice(0,18)!,255,650); ctx.font="26px PingFangSC-Semibold"; ctx.fillStyle = '#1C3063'; ctx.textAlign='center'; ctx.fillText(dependce.slice(18)!,255,678); // 這個坐標點的位置也需要重新計算 }else{ ctx.font="26px PingFangSC-Semibold"; ctx.fillStyle = '#1C3063'; ctx.textAlign='center'; ctx.fillText(dependce,255,650); } } let data = canvas.toDataURL(); // 這里其實我們的圖就畫好了,接下來就是根據自己的代碼邏輯進行操作了。
// 這里是將我們需要的一些參數尤其是生成的圖片放到一個數組中去,然后傳遞到父級。 this.exportArr.push({hospital: this.data.hospital!,department:this.data.department!,name:this.data.name!,img:data}); this.$emit('exportArr',this.exportArr);// 如果不需要向父組件傳值的話,可以省略 } } }
經過上面的方法,我們其實就可以拿到繪制好的圖片的base64格式了,我們就可以執行上面的導出過程了。
// 給圖片元素賦值,這里的bgImg最好是一個絕對路徑,如果是相對路徑的話,需要借助