幾行代碼教你解決微信生成海報及二維碼

現現在圍繞微信生態相關開發已經很是常見,本期帶來如何經過 qrcode.js 實現微信內置瀏覽器動態生成二維碼並可以長按識別 以及 經過 html2canvas 生成圖片並長按保存css

說幾個知識點

  • 微信長按彈出識別選項的原理
    • 微信客戶端檢測到用戶長按img標籤
    • 微信主動進行截屏並識別圖片,二維碼識別採用的是截屏而不是經過img標籤
    • 微信識別成功後執行相關操做
  • Base64
    • Base64是網絡上最多見的用於傳輸8Bit字節碼的編碼方式之一,Base64就是一種基於64個可打印字符來表示二進制數據的方法
  • Blob
    • HTML5中的Blob對象與MySQL中的BLOB對象有區別,HTML5中的Blob對象除了存放二進制數據外還能夠設置這個數據的MINE類型,這至關於對文件的存儲,其它不少二進制對象也是從這個對象繼承的
  • canvas.toDataURL([type, encoderOptions])
    • type : 指定圖片類型,默認值 image/png
    • encoderOptions : 爲 image/jpegimage/webp 類型的圖片設置圖片質量,取值0-1,超出則以默認值0.92替代
    • 做用: 經過canvas進行轉化圖片

準備工做

  • 結合微信規範明確需求
    • 微信img標籤經過src屬性可實現長按彈出選項(保存至手機,圖片爲二維碼的狀況下會出現識別二維碼)
    • 二維碼圖片若爲本地圖片或服務器圖片(即不須要進行動態生成)只須要正常編寫代碼便可實現
    • 微信針對內置瀏覽器內的頁面圖片有着本身的一套適應邏輯與規範,canvas的圖片和base64編碼格式的圖片在安卓與ios手機上會出現不一樣的問題
  • 肯定實現方案
    • 本例採用第三方js庫實現生成二維碼
    • 針對生成的base64編碼的圖片微信沒法長按識別須要在前端進行格式和image對象從新轉換
    • 生成的圖片彈窗展現,避免出現其餘元素影響微信識別率

開發環境

  • 開發平臺
    • MacOS
  • 開發環境
    • Vue + node
  • 客戶端環境
    • Google Chrome
    • Wechat Webview

技術實現

本例的技術實現方案均在Vue項目環境下實現的html

引入第三方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'

組件中調用

  • HTMLvue

    <div class="qrcode-panel" id="qrcode"></div>
  • JSnode

    • 簡單調用
    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 對象沒法在微信端長按識別ios

    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節點中,在關閉操做時須要將以前生成的 canvasimage 去除

微信內置瀏覽器生成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;
	});
}

實現效果

源碼地址

寫在最後

  • 若是你以爲這篇文章對你有益,煩請點贊以及分享給更多須要的人!

快到碗裏來!百度校招還有HC!甩簡從來!

極速直接內推【字節跳動】&【百度】&【猿輔導】&【京東】

歡迎關注微信公衆號【全棧道路】,獲取更多科技相關知識及免費書籍。

更多好文

冷門的HTML - tabindex 的做用git

[萬字長文]百度和好將來面試經含答案github

[前端面試]前端緩存問題看這篇,讓面試官愛上你web

記一次慘痛的Vue-cli + VueX + SSR經歷面試

[三分鐘小文]前端性能優化-HTML、CSS、JS部分

[三分鐘小文]前端性能優化-頁面加載速度優化

[三分鐘小文]前端性能優化-網絡傳輸層優化

相關文章
相關標籤/搜索