轉載:zgh0711:https://blog.csdn.net/zgh0711/article/details/88192993
如何生成二維碼
現在前端環境下,要生成二維碼,可用的工具庫有很多,我這里用的是 qrcode,首先安裝
npm install --save qrcode
安裝完之后 import 導入就能使用了
import QRCode from 'qrcode'
一,將生成的二維碼通過 canvas 標簽展示
<canvas class="qr" id="qrCode-canvas"></canvas>
let canvas = document.getElementById('qrCode-canvas') QRCode.toCanvas(canvas, this.qrCodeUrl, (error) => { if (error) { console.log(error) } else { canvas.style.width = '1.68rem' canvas.style.height = '1.68rem' }); } })
二維碼生成好后,有需要的話可以調整下 canvas 的大小等屬性,因為 qrcode 生成的二維碼會帶有一些默認樣式,需要調整下。
二,先通過 canvas 生成二維碼,然后將 canvas 的內容轉為 base64 格式以 img 標簽展示
<img class="qr" id="qr-img" :src="dataUrl" alt="邀請二維碼"/> let img = document.getElementById('qr-img') let canvas = document.createElement('canvas') canvas.width = img.width canvas.height = img.height //用 canvas 對象和邀請鏈接生成二維碼,並將生成的二維碼轉為 base64 QRCode.toCanvas(canvas, this.qrCodeUrl, (error) => { if (error) { console.log(error) } else { this.dataUrl = canvas.toDataURL("image/jpeg") }); } })
上面兩種方式都可以生成二維碼並顯示在界面上,區別在於第一種是以 canvas 標簽顯示,在微信中長按是無法識別的。第二種是以 img 標簽顯示,在微信中長按會自動識別並可以直接以圖片形式分享出去。
做到這一步,需求已經完成了一半,下一步就是按設計圖要求把二維碼定位到海報背景上,將二維碼和海報合成為一張圖片。之所以要合成為一張圖片還是為了讓用戶在微信中操作方便。合成為一張圖片后,用戶在微信中直接長按合成后的海報就可以分享或者識別二維碼。
合成海報時碰到的坑
合成海報時需要用到另一個工具庫 html2canvas ,基本使用方法也很簡單,先獲取要合成圖片的 dom 對象,然后調用 html2canvas ,它會返回一個 promise,里面的 canvas 就是合成后的圖片信息,同樣的,這里的 canvas 可以直接顯示出來,也可以轉成 base64 之后放到 img 標簽里顯示,但是為了分享或者下載方便,基本都是轉成了 base64
let poster = document.getElementById('poster') html2canvas(poster).then(canvas => { this.posterDataUrl = canvas.toDataURL() });
到這里,基本需求就完成了。然而世界上的事情往往都不會是一帆風順的,在測試的時候發現出了問題。
我前面二維碼是用上面說的第二種方法顯示的,將二維碼的 canvas 轉成了 base64 顯示在 img 標簽上,再將這個二維碼 img 和海報背景 img 合成。這樣的實現方式在 iOS 和瀏覽器中都沒有問題,然而在安卓版微信里面卻是只有海報背景而沒有二維碼。
在查了N多資料和嘗試了好多遍之后終於發現,是因為我的二維碼是 base64 的,如果二維碼是以 canvas 形式顯示,再去合成海報,將合成后的海報轉為 base64 就沒有問題了。 所以我在前面寫生成二維碼的時候寫了二種方法。至此,整個需求也就真正的完成了。
下面是完整代碼
<template> <div class="ypl-flex"> <mt-header title="邀請用戶" go-back></mt-header> <div class="invitePosterPage flex"> <p class="title">分享專屬海報,邀請用戶注冊,即可成功邀請</p> <p class="remark">(注:只能通過此二維碼注冊用戶才可成功邀請)</p> <img v-if="posterDataUrl" :src="posterDataUrl" class="poster-bg" alt="邀請海報"/> <div v-else id="poster" class="flex-row" style="position: relative"> <img class="poster-bg" src="../../../assets/img/img_poster_bg.png" alt="邀請海報背景"/> <canvas class="qr" id="qrCode-canvas"></canvas> </div> </div> </div> </template> <script> /** * 這是邀請海報組件 */ import QRCode from 'qrcode' import html2canvas from 'html2canvas'; export default { name: 'Poster', data () { return { posterDataUrl:'', qrCodeUrl: 'https://www.baidu.com' } }, async mounted () { this.createQRCode() }, methods: { createQRCode () { //先用 QRCode 生成二維碼 canvas,然后用 html2canvas 合成整張海報並轉成 base64 顯示出來 let canvas = document.getElementById('qrCode-canvas') QRCode.toCanvas(canvas, this.qrCodeUrl, (error) => { if (error) { console.log(error) } else { //qrcode 生成的二維碼會帶有一些默認樣式,需要調整下 canvas.style.width = '1.68rem' canvas.style.height = '1.68rem' let poster = document.getElementById('poster') html2canvas(poster).then(canvas => { this.posterDataUrl = canvas.toDataURL() }); } }) } }, } </script>
這次做這個需求的過程中,查到了一些 html2canvas 的資料,有很多文章都提到 html2canvas 有一些坑,我是沒碰到,現在將這些文章列出來,給需要的人。
html2canvas 用法詳解
Html2canvas - 項目中遇到的那些坑點匯總(更新中…)
一次 H5 「保存頁面為圖片」 的踩坑之旅
微信H5實現網頁長按保存圖片及識別二維碼
基於html2canvas實現網頁保存為圖片及圖片清晰度優化
Vue.js結合Canvas制作二維碼和圖片的合成(qrcanvas + html2canvas)
然后就是 canvas 轉 base64 的 .toDataURL()] 這個方法,這個方法里面其實是可以配置參數的,有需要的可以去看下這個文檔
HTMLCanvasElement.toDataURL()