小程序开发-利用canvas实现保存二维码海报到本机
場(chǎng)景及需求
在小程序開發(fā)過(guò)程中,經(jīng)常需要實(shí)現(xiàn)保存某個(gè)頁(yè)面為帶小程序碼的二維碼海報(bào)圖片到本地,然后用于分享或者發(fā)朋友圈等操作。
主要技術(shù)點(diǎn)及小程序相關(guān)api
技術(shù)注意事項(xiàng)
- 小程序的canvas與H5 canvas使用api大部分一致,但由于小程序中沒(méi)有DOM節(jié)點(diǎn)的概念,所以不能使用很多現(xiàn)成的工具庫(kù)
- 小程序canvas默認(rèn)寬度300px、高度225px
- 小程序canvas相關(guān)的api中單位為px,并非rpx,所以在業(yè)務(wù)實(shí)現(xiàn)過(guò)程中需要處理適配
- 小程序canvas對(duì)跨域圖片不支持,需要先將圖片緩存到本地
技術(shù)點(diǎn)
- wx.getImageInfo()
- wx.getSystemInfo()
- wx.canvasToTempFilePath()
- wx.saveImageToPhotosAlbum()
- canvas渲染相關(guān)api
整體流程
1.先獲取所有圖片資源,線上圖片需要緩存到本地,使用圖片的本地路徑做渲染
2.獲取設(shè)備信息,根據(jù)設(shè)備寬度計(jì)算出寬度因子x
3.繪制canvas
4.將canvas轉(zhuǎn)化為圖片,將圖片保存到本機(jī)
實(shí)現(xiàn)
寬度因子x及元素寬度的尺寸計(jì)算
rpx(responsive pixel): 可以根據(jù)屏幕寬度進(jìn)行自適應(yīng)。規(guī)定屏幕寬為750rpx。如在 iPhone6 上,屏幕寬度為375px,共有750個(gè)物理像素,則750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。
參考文檔: 小程序-WXSS-尺寸單位
由文檔可以看出不同的設(shè)備,寬度是不同數(shù)值的px,但是均為750rpx,由此可以利用750rpx計(jì)算出寬度因子x:
設(shè)備寬度 / 750
以設(shè)計(jì)稿寬度750rpx為例,則在不同設(shè)備下,設(shè)計(jì)稿寬度y在不同設(shè)備下的px寬度均為:
Y = y * x
Y = y * (設(shè)備寬度 / 750)
由此,在實(shí)現(xiàn)中,canvas標(biāo)簽寬高需要設(shè)置為變量,且使用微信提供的 wx.getSystemInfo() 接口獲取設(shè)備寬度信息后,進(jìn)行計(jì)算
<canvas canvas-id="qrcode-canvas" :style="{width: canvas.width + 'px', height: canvas.height + 'px'}"></canvas> 復(fù)制代碼// wx.js // 獲取設(shè)備基本信息 export function wxGetSystemInfo () {return new Promise(async function (resolve, reject) {wx.getSystemInfo({success: function (res) {resolve(res);},fail: function (err) {reject(err);}})}); } // demo.vue // 獲取手機(jī)基本信息 async getPhoneSystemInfo () {let _this = this;let systemInfoRes = await wxGetSystemInfo();_this.canvas.width = systemInfoRes.screenWidth;// 設(shè)計(jì)稿寬高為 750 * 912_this.canvas.height = 912 / 750 * _this.canvas.width;_this.storageQrcode(); }, 復(fù)制代碼獲取遠(yuǎn)程圖片緩存到本地使用
- api
- wx.getImageInfo()
- 參考文檔: wx.getImageInfo()
注意:如果是本地圖片,即'static'文件夾中的圖片,如'/static/logo.png'經(jīng)過(guò)wx.getImageInfo返回的path會(huì)省去開頭的'/',即'static/logo.png',這會(huì)導(dǎo)致拿不到資源,所以本地圖片不需要調(diào)用wx.getImageInfo()進(jìn)行本地緩存
// wx.js // 獲取圖片基本信息 export function wxGetImgInfo (imgUrl) {return new Promise(async function (resolve, reject) {wx.getImageInfo({src: imgUrl,success: function (res) {resolve(res);},fail: function (err) {reject(err);}})}); } // demo.vue // 緩存遠(yuǎn)程圖片 async storageQrcode () {let _this = this;// 背景圖url轉(zhuǎn)path// let bgRes = await wxGetImgInfo(_this.bgImg);// _this.imgPath.bgImg = bgRes.path;// Logo url轉(zhuǎn)path// let logoRes = await wxGetImgInfo(_this.logo);// _this.imgPath.logo = logoRes.path;// 頭像 url轉(zhuǎn)path// let headerImgRes = await wxGetImgInfo(_this.cardDetail.header);// _this.imgPath.headerImg = headerImgRes.path;// 二維碼 url轉(zhuǎn)pathlet qrCodeRes = await wxGetImgInfo(_this.qrCode);_this.imgPath.qrCode = qrCodeRes.path;console.log(_this.imgPath);// _this.initCanvas(_this.canvas.width); }, 復(fù)制代碼繪制canvas
canvas繪制主要用到了圖片繪制、文字繪制,圖片繪制及文字繪制的時(shí)候,需要引入上文說(shuō)到的寬度因子x進(jìn)行計(jì)算
圖片繪制
- canvasContext.drawImage
- 參考文檔: canvasContext.drawImage
這里的圖片繪制之前先計(jì)算寬度因子
let _this = this;// variableVal即為上文拿到的設(shè)備寬度const variableNum = variableVal / 750; // 根據(jù)設(shè)備寬度算出一個(gè)rpx為多少pxconst ctx = wx.createCanvasContext('qrcode-canvas');// 清除畫布上矩形的內(nèi)容ctx.clearRect(0, 0, 0, 0);// 繪制上部card背景圖const bgImgDesc = {url: _this.imgPath.bgImg,left: 0,top: 0,width: 750 * variableNum,height: 912 * variableNum};ctx.drawImage(bgImgDesc.url, bgImgDesc.left, bgImgDesc.top, bgImgDesc.width, bgImgDesc.height);ctx.draw(); 復(fù)制代碼文字的繪制
- canvasContext.setFillStyle - 設(shè)置顏色
- canvasContext.setFontSize - 設(shè)置大小
- canvasContext.fillText - 填充文本
canvas轉(zhuǎn)圖片并保存到本地
- wx.canvasToTempFilePath - canvas轉(zhuǎn)圖片
- 參考文檔: wx.canvasToTempFilePath
- wx.saveImageToPhotosAlbum - 保存圖片到本地
- 參考文檔: wx.saveImageToPhotosAlbum
注意點(diǎn)
tip: wx.canvasToTempFilePath() 在 draw 回調(diào)里調(diào)用該方法才能保證圖片導(dǎo)出成功。
由于導(dǎo)出圖片需要在canvas繪制圖片的draw()方法回調(diào)中使用才能,所以我們?cè)诶L制canvas的時(shí)候直接轉(zhuǎn)canvas為圖片,然后將路徑存下來(lái),點(diǎn)擊下載的時(shí)候,再直接拿圖片路徑進(jìn)行下載操作。
// wx.js // canvas畫布轉(zhuǎn)圖片 export function wxCanvasToTempFilePath (canvasObj) {return new Promise(async function (resolve, reject) {wx.canvasToTempFilePath({x: canvasObj.x,y: canvasObj.y,width: canvasObj.width,height: canvasObj.height,destWidth: canvasObj.destWidth,destHeight: canvasObj.destHeight,canvasId: canvasObj.canvasId,fileType: canvasObj.fileType ? canvasObj.fileType : 'png',success: function (res) {resolve(res);},fail: function (err) {reject(err);}})}); } // demo.vue // 繪制canvas initCanvas () {let _this = this;// 繪制canvas......ctx.draw(false, function () {_this.saveImg();}); }, // 將canvas轉(zhuǎn)為圖片 async saveImg () {let _this = this;const canvasObj = {x: 0,y: 0,width: _this.canvas.width,height: _this.canvas.height,destWidth: _this.canvas.width * 4,destHeight: _this.canvas.height * 4,canvasId: 'qrcode-canvas',fileType: 'png'};let imgRes = await wxCanvasToTempFilePath(canvasObj);_this.qrCodeImgPath = imgRes.tempFilePath; }, 復(fù)制代碼下載圖片到本地
<canvas canvas-id="qrcode-canvas" :style="{width: canvas.width + 'px', height: canvas.height + 'px'}"></canvas> <button type="primary" plain="true" @click="downLoadImg"> 保存二維碼 </button> 復(fù)制代碼// wx.js // 保存圖片到本地 export function wxSaveImageToPhotosAlbum (filePath) {return new Promise(async function (resolve, reject) {wx.saveImageToPhotosAlbum({filePath: filePath,success: function (res) {resolve(res);},fail: function (err) {reject(err);}})}); } // demo.vue // 保存圖片到本機(jī) async downLoadImg () {let _this = this;let saveRes = await wxSaveImageToPhotosAlbum(_this.qrCodeImgPath);if (saveRes.errMsg === 'saveImageToPhotosAlbum:ok') {wx.showToast({duration: 3000,icon: 'none',title: '保存圖片成功!',mask: true});} else {wx.showToast({duration: 3000,icon: 'none',title: '保存圖片失敗,請(qǐng)重試!',mask: true});} }, 復(fù)制代碼demo代碼已經(jīng)放在 './demo' 文件夾,歡迎交流
總結(jié)
在業(yè)務(wù)實(shí)現(xiàn)中,我們只要把業(yè)務(wù)流程進(jìn)行分割,然后一步一步去實(shí)現(xiàn),捋明白流程之后各個(gè)擊破很多第一反應(yīng)去查找已有的庫(kù)來(lái)實(shí)現(xiàn)的功能自己實(shí)現(xiàn)起來(lái)也很簡(jiǎn)單。
在某種意義上,自己弄明白原理之后去實(shí)現(xiàn)反而更加輕松,更加得心應(yīng)手。
-- LucaLJX: github:https://github.com/LucaLJX
總結(jié)
以上是生活随笔為你收集整理的小程序开发-利用canvas实现保存二维码海报到本机的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 了解WWW服务与HTTP协议 【入门与应
- 下一篇: 线性表之栈