前端如何優雅的製作帶LOGO的二維碼

Color..「Blind」發表於2018-07-18

說在前面的話...

最近專案有個功能產品列表,可以將不同產品生成不同的二維碼,掃碼可以進入對應的產品詳情頁,同時二維碼需要帶公司logo,需要可以長按調起微信的下載圖片的功能,其實也就是說,最後生成的二維碼是一個圖片

首先介紹一個比較出名的生成二維碼的外掛QRcode

  1. 這個外掛是基於jq封裝的所以在使用時需要先引入jq
  2. 用法也比較簡單 直接上程式碼
<div id="qrcode" class="qrcode clip"></div>
<canvas id="myCanvas" width="200" height="200" class="qrcode clip"></canvas>
<img id="canvasImg" alt="" width="200" height="200" class="qrcode">
let src = "/static/imgs/settle.png"; //想顯示的二維碼中間的圖片
$("#qrcode").qrcode({
 	render: "canvas", //設定渲染方式,有table和canvas,使用canvas方式渲染效能相對來說比較好
	text: ``, //掃描二維碼後顯示的內容,可以直接填一個網址,掃描二維碼後自動跳向該連結
	width: "200", //二維碼的寬度
	height: "200", //二維碼的高度
	background: "#ffffff", //二維碼的後景色
	foreground: "#000000", //二維碼的前景色
	src: src //二維碼中間的圖片
});
複製程式碼

這樣操作大家會發現已經顯示了帶logo的二維碼,細心的同學會發現,當我們在手機中開啟頁面時,並不能調起長按儲存二維碼,原因是我們拿外掛生成是canvas並不是img,所以後面我們要進入真正的主題,利用canvas生成圖片

利用canvas生成圖片

  • 首先整理一下思路,從上面的方法中我們已經得到了canvas ,那canvas可不可以直接轉成圖片呢
  • 引入canvas.toDataURL(),這個方法是將canvas轉化成base64,base64可以作為img的src,就可以成功的將canvas轉化成圖片,引數我們可以定義是想轉化為何種形式的圖片,我這裡用的toDataURL("image/png")
    convertCanvasToImage() {
        var canvas = $("#qrcode canvas")[0].toDataURL("image/png")
        return canvas
     }
    複製程式碼
  • 但是當我們轉化完成之後卻發現,轉化出來的base64展示出來只是一張二維碼,並沒有logo,我分析應該外掛沒有真正的將logo合成上去,我們需要將logo和base64合成一張圖片,所以需要利用canvas合成圖片

利用canvas合成圖片

  • 那麼首先我們整理一下思路,其實我們要做的就是利用canvas的drawImage畫圖片功能先後將base64.和logo畫上去,最後再一起轉成base64
  • 這裡有一個問題是畫圖時我們是需要用到img.onload方法,而這個方法是非同步,且需要本地服務支援,有些同學可能會在本地靜態頁面寫demo ,卻展示不出最後合成的base64,就是因為無服務的原因。所以需要利用node,或者放在類似vue ng 這類專案中 看效果
export function creatEwm(base64, canvas,callback) {
 var ctx = canvas.getContext("2d");
 var img = document.createElement('img');
 img.src = '/static/imgs/icon-phone.png'
 img.onload = function () {
   var imgUpload = new Image();
   imgUpload.src = base64();
   imgUpload.onload = function () {
     // 繪製
     ctx.drawImage(imgUpload, 0, 0, 200, 200);
     ctx.drawImage(img, 78, 80, 40, 40);
     callback(canvas.toDataURL("image/png"))
   };
 }
}
複製程式碼
  • 上面我封裝了一下生成最後base64的方法
  • 引數一base64是我們第一次拿qrcode生成二維碼的base64也就是我上面寫的convertCanvasToImage方法的返回值
  • 引數二是獲取到的需要繪製的canvas的節點,這裡與qrcode 的節點不同 需從新定義,也就是我在最開始定義id為myCanvas的canvas標籤
  • 引數三是傳回撥,因為上面講到,img.onload是非同步載入,我們是拿不到最後的base64,可以通過回撥的方式獲取到非同步資料,當然也可以用promise等方式
  • 方法中,引入了需要的logo 但此次並沒有任何地方承載這個圖片。所以我們需要新建一個空img標籤去承載,後面才可以用drawImage方法,當然用new Image()方法也是可以
  • 同理傳入的base64也需要這麼做。
  • 為什麼使用img.onload?原因是我們需等待圖片載入完成再去進行操作,且圖片載入的方法最好巢狀寫,等圖片1載入完載入圖片2
  • 最後傳入回撥將獲取的最後的base 以src的方式渲染到html中
creatEwm(this.convertCanvasToImage, document.getElementById('myCanvas'), function (dataUrl) {
   document.getElementById("canvasImg").src = dataUrl
})
複製程式碼

總結

以上就完成了前端去生成二維碼,且封裝後,在頁面中寫入的程式碼很少,就可以實現不同的二維碼帶不同的資訊,且可以調起長按下載圖片。

相關文章