現如今圍繞微信生態相關開發已經非常常見,本期帶來如何通過
qrcode.js
實現微信內建瀏覽器動態生成二維碼並能夠長按識別 以及 通過html2canvas
生成圖片並長按儲存
說幾個知識點
- 微信長按彈出識別選項的原理
- 微信客戶端檢測到使用者長按
img
標籤 - 微信主動進行截圖並識別圖片,二維碼識別採用的是截圖而不是通過
img
標籤 - 微信識別成功後執行相關操作
- 微信客戶端檢測到使用者長按
- Base64
- Base64是網路上最常見的用於傳輸8Bit位元組碼的編碼方式之一,Base64就是一種基於64個可列印字元來表示二進位制資料的方法
- Blob
- HTML5中的Blob物件與MySQL中的BLOB物件有區別,HTML5中的Blob物件除了存放二進位制資料外還可以設定這個資料的MINE型別,這相當於對檔案的儲存,其它很多二進位制物件也是從這個物件繼承的
canvas.toDataURL([type, encoderOptions])
type
: 指定圖片型別,預設值image/png
encoderOptions
: 為image/jpeg
或image/webp
型別的圖片設定圖片質量,取值0-1,超出則以預設值0.92替代- 作用: 通過canvas進行轉化圖片
準備工作
- 結合微信規範明確需求
- 微信img標籤通過src屬性可實現長按彈出選項(儲存至手機,圖片為二維碼的情況下會出現識別二維碼)
- 二維碼圖片若為本地圖片或伺服器圖片(即不需要進行動態生成)只需要正常編寫程式碼即可實現
- 微信針對內建瀏覽器內的頁面圖片有著自己的一套適應邏輯與規範,canvas的圖片和base64編碼格式的圖片在安卓與ios手機上會出現不同的問題
- 確定實現方案
- 本例採用第三方js庫實現生成二維碼
- 針對生成的base64編碼的圖片微信無法長按識別需要在前端進行格式和image物件重新轉換
- 生成的圖片彈窗展示,避免出現其他元素影響微信識別率
開發環境
- 開發平臺
- MacOS
- 開發環境
- Vue + node
- 客戶端環境
- Google Chrome
- Wechat Webview
技術實現
本例的技術實現方案均在Vue專案環境下實現的
引入第三方js庫
-
提供兩種引入方式,兩種方式是不同的js庫,方便大家選擇和使用
- 本地引入
qrcode.js
// qrcode.js官方GitHub文件: https://github.com/davidshimjs/qrcodejs <script src="static/js/qrcode.js"></script>
- npm 引入
qrcodejs2
npm install qrcodejs2 import qrCode from 'qrcodejs2'
- 本地引入
元件中呼叫
-
HTML
<div class="qrcode-panel" id="qrcode"></div>
-
JS
- 簡單呼叫
new QRCode(document.getElementById('qrcode'), 'your content'); // new QRCode(element, option) // element 顯示二維碼的元素或該元素的 ID // option 引數配置
- 標準呼叫
var qrcode = new QRCode(document.getElementById("qrcode"), { text: "https://www.xxx.com?did=123456&id=123&userid=456", width: 160, //影像寬度 height: 160, // 影像高度 render: 'canvas', // 生成格式(table 和 canvas) colorDark : "#000000", //前景色 colorLight : "#ffffff", //背景色 correctLevel : QRCode.CorrectLevel.H // 容錯級別 }); // 容錯級別,可設定為: QRCode.CorrectLevel.L(最大 7% 的錯誤能夠被糾正) QRCode.CorrectLevel.M(最大 15% 的錯誤能夠被糾正) QRCode.CorrectLevel.Q(最大 25% 的錯誤能夠被糾正) QRCode.CorrectLevel.H(最大 30% 的錯誤能夠被糾正)
- 其他公共方法
QRCode.makeCode(text) // 設定二維碼內容 QRCode.clear() // 清除二維碼
重置 Image 物件
-
重置的原因是原JS生成的 image 和 canvas 物件無法在微信端長按識別
var canvas = document.getElementsByTagName('canvas')[0]; var img = this.convertCanvasToImage(canvas); document.getElementById("qrcode").append(img); convertCanvasToImage(canvas) { //新建Image物件 var image = new Image(); // canvas.toDataURL 返回的是一串Base64編碼的URL image.src = canvas.toDataURL("image/png"); image.id = 'qrcodeImg'; return image; }
後續細節處理
- 至此,一個能夠滿足長按識別的動態二維碼已經生成,不繼續處理的話會有兩張二維碼,長按對比就能看出,
qrcode.js
生成的二維碼長按無法識別,而經過重置之後的物件是可以實現此功能的。 - 我的處理方式是兩個二維碼都保留,將二維碼圖片進行重新定位,將重置的二維碼圖片置於不能識別二維碼上層,不去頻繁操作DOM節點的顯示隱藏。
- 生成的二維碼通過
append
的方式插入到dom節點中,在關閉操作時需要將之前生成的canvas
和image
去除
微信內建瀏覽器生成canvas圖片儲存
- 上述教程可以實現動態生成二維碼進行儲存和長按識別,但是如果需要將HTML內容生成canvas儲存就存在問題了。
- 針對儲存需要注意的幾個問題:
- canvas禁止跨域
- 安卓微信長按不能儲存base64圖片
- 微信限制Blob型別圖片的儲存
- 使用
canvas.toDataURL
繪製時的型別使用image/jpeg
進行儲存
技術選型
- 使用第三方JS庫
html2canvas
進行處理 - 識別和生成原理:
- 指令碼直接在使用者瀏覽器上擷取網頁或部分網頁的"螢幕截圖"
- "螢幕截圖"基於DOM,因此它可能不是真實表示的100%準確,因為它沒有製作實際的螢幕截圖,而是根據頁面上可用的資訊構建螢幕截圖
- 存在的問題:
- 正是因為
html2canvas
不是基於真正的螢幕截圖去識別處理,所以脫離了文件流,或者文件流異常的元素會無法被擷取下來 html2canvas
只會擷取到目標元素寬高範圍內的內容- 對部分css樣式支援不好,相容性差的屬性列表
- 正是因為
- 一些可能需要的引數
useCORS
: 是否嘗試使用CORS從伺服器載入影像async
: 是否非同步解析和呈現元素scale
: 用於渲染的比例。預設為瀏覽器裝置畫素比率window.devicePixelRatio
allowTaint
: 是否允許畫布被汙染,被汙染的canvas是沒法使用toDataURL()轉base64流的,部分細節請 參考這裡- 更多
html2canvas
引數請點選這裡
引入第三方JS庫
- 使用
html2canvas
import html2canvas from 'html2canvas'
元件中呼叫
- HTML
<div class="html2canvas-conetent" ref="canvasContent">
<img src="/static/images/canvas.jpg">
<span>測試Title</span>
</div>
<button @click="showCanvas()">生成canvas圖片</button>
- JS
- 使用
html2canvas
推薦的promise方法
- 使用
showCanvas() {
let self = this;
html2canvas(self.$refs.canvasContent).then(function(canvas) {
self.imgUrl = canvas.toDataURL();
self.showCanvasImg = true;
});
}
// 非同步解析呼叫和呈現元素
showCanvas() {
let self = this;
html2canvas(self.$refs.canvasContent {
async: true
}).then(canvas => {
self.imgUrl = canvas.toDataURL();
self.showCanvasImg = true;
});
}
實現效果
原始碼地址
寫在最後
- 如果你覺得這篇文章對你有益,煩請點贊以及分享給更多需要的人!