Before starting to implement it, let’s take a look at the renderings.
tips 1. Network images need to be configured with a download domain name first, which can be converted to a temporary path through wx.getImageInfo ;
2. Due to personal habits, I am accustomed to using async-await syntax, so I need to introduce the regenerator library. The usage method can be checked online.
1. Encapsulate the general WeChat API and return it as a Promise object/datas/common.js
//Encapsulate the WeChat image information. export const getWxImageInfo = (imgPath) => { return new Promise((resolve, reject) => { wx.getImageInfo({ src: imgPath, success: res => { resolve(res) }, fail: res => { reject (res) } }) })}// Encapsulates obtaining node selector information export const getSelectQurey = (queryStr) => { return new Promise(resolve => { var query = wx.createSelectorQuery(); query.select(queryStr).boundingClientRect(); query.exec(res => { resolve(res) }) })}// The package exports the canvas to generate a picture of a specified size export const canvasToTempFilePath = (width, height, canvasId, fileType = 'jpg') => { return new Promise((resolve, reject) => { wx.canvasToTempFilePath({ width, height, canvasId, fileType, success: res => { resolve(res) }, fail: res => { reject(res) } }) })}//Encapsulate and save images to the system album export const saveImageToPhotosAlbum = (filePath) => { return new Promise((resolve, reject) => { wx.saveImageToPhotosAlbum({ filePath, success: res => { resolve(res) }, fail: res => { reject(res) } }) })} 2. Implementation of views.wxml
<view class=icon-download catchtap=getCanvas>Click to generate image</view><!-- Large QR code image--><view class='shade' wx:if={{isShowCanvas}}> <view class ='qr-code'> <canvas class='qr-canvas' canvas-id=qrCanvas id=qrCanvas></canvas> <view class='qr-btn'> <view class='qr-btn-save' catchtap='saveImageToPhotosAlbumFunc'>Save the picture and share it with friends</view> <view class='qr-btn-cancel' catchtap='hideCanvas'>Cancel</view> </view view> </view></view><!-- QR code large image.end -->.wxss
/* View large image*/.shade { width: 100%; height: 100%; background-color: rgba(240, 235, 235, 0.5); position: fixed; z-index: 100; top: 0; left : 0;}.qr-code { width: 600rpx; height: 1000rpx; background-color: #fff; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); /* margin: 30rpx auto; */}.qr-canvas { display: block; background-color: #fff ; margin: 0 auto; width: 600rpx; height: 900rpx;}.qr-btn { width: 600rpx; height: 100rpx; line-height: 100rpx; margin: 0 auto; font-size: 28rpx; color: #fff; display: flex; background-color: #658dc5;}.qr-btn-save { flex: 0 0 500rpx; text -align: center; border-right: 1rpx solid #fff;}.qr-btn-cancel { text-align: center; flex: 0 0 100rpx;} 3. Create canvas and save it to the system albumtips
The product image is square, so the width and height of the product image here are based on the width of the canvas. The text cannot be wrapped. This is just a simple process.
Note: There is a sentence in the document that you need to pay attention to when using wx.canvasToTempFilePath(Object object, Object this) : Export the contents of the specified area of the current canvas to generate a picture of the specified size. Only by calling this method in the draw() callback can the image be exported successfully.
const app = getApp()const regeneratorRuntime = app.globalData.regeneratorRuntimeconstconst util = require('../../utils/util.js')import { getSelectQurey, getWxImageInfo, canvasToTempFilePath, saveImageToPhotosAlbum} from '../../ datas/common.js'Page({ data: { isShowCanvas: false, // Whether to display canvas wxaCode: 'https://xxx..jpg', // Product applet code goodsImageUrl: 'https://xxx..jpg', // Product image canvasTempFilePath: '', //Canvas exports the temporary path to generate images}, //Click to display the canvas to be generated getCanvas(e) { if (!this.data.wxaCode) { util.showToast('QR code generation failed'); return; } this.setData({ isShowCanvas: true }, () => { this.createCanvas(); }) }, // Hide canvas hideCanvas() { this .setData({ isShowCanvas: false }) }, // Create canvas async createCanvas() { wx.showLoading({ title: 'Image is being generated...' }) const _this = this // Create a node selector const res = await getSelectQurey('#qrCanvas'); // The width and height of the canvas const cvWidth = res[0].width; const cvHeight = res[0].height; const cvSubValue = cvHeight - cvWidth const qrWidth = cvSubValue / 1.5 const qrMargin = (cvSubValue - qrWidth) / 2 const qrX = cvWidth - qrWidth - qrMargin / 2 const qrY = cvWidth + qrMargin const shopNameY = cvWidth + cvSubValue - qrWidth // QR code network image to temporary path let qrImagePath = ''; try { const wxaCode = _this.data.wxaCode; const qrImage = await getWxImageInfo(wxaCode); qrImagePath = qrImage.path } catch (e) { wx.hideLoading(); this.hideCanvas(); util.showToast('QR code Generation failed'); return; } // Product network pictures to temporary path let goodsImagePath = '/images/default_goods.png'; const goodsImage = _this.data.goodsImageUrl; if (goodsImage) { const goodsImageRes = await getWxImageInfo(goodsImage); goodsImagePath = goodsImageRes.path; } // Create canvas var ctx = wx.createCanvasContext('qrCanvas', _this); // Set the background ctx.setFillStyle('#fff'); ctx.fillRect(0, 0, cvWidth, cvHeight); // Set the width and height of the product image to be the same ctx.drawImage(goodsImagePath, 0, 0, cvWidth, cvWidth); // Set the QR code image ctx.drawImage(qrImagePath, qrX, qrY, qrWidth, qrWidth); // Set the shop name const shopName = 'I am the shop name'; ctx.setFillStyle('black') ctx.setFontSize(16) ctx .setTextAlign('left') ctx.fillText(shopName, 10, shopNameY, cvWidth - qrWidth); // Set the product name text so that it cannot wrap. This is just a simple process. const goodsName = 'A product with a very long name will ask you if you are afraid'; let goodsName1 = ''; let goodsName2 = ''; ctx.setFillStyle('black') ctx.setFontSize(14) ctx.setTextAlign('left') if (goodsName.length <= 10) { ctx.fillText(goodsName, 10, shopNameY + 30, cvWidth - qrWidth); } else if (goodsName.length > 10 && goodsName.length <= 22) { goodsName1 = goodsName.substring( 0, 10); goodsName2 = goodsName.substring(10); ctx.fillText(goodsName1, 10, shopNameY + 30, cvWidth - qrWidth); ctx.fillText(goodsName2, 10, shopNameY + 50, cvWidth - qrWidth); } else { goodsName1 = goodsName.substring(0, 10); goodsName2 = goodsName.substring(10, 22) + '...'; ctx.fillText(goodsName1, 10, shopNameY + 30, cvWidth - qrWidth); ctx.fillText(goodsName2, 10, shopNameY + 50, cvWidth - qrWidth); } // Set tip const tipText = 'Long Press the identification applet and place an order now! '; ctx.setFillStyle('gray') ctx.setFontSize(8) ctx.setTextAlign('center') ctx.fillText(tipText, cvWidth / 2, cvHeight - 10); // Complete ctx.draw(false, () => { wx.hideLoading(); _this.canvasToTempFilePathFunc(cvWidth, cvHeight, 'qrCanvas') }); }, // Export the contents of the specified area of the current canvas to generate a picture of the specified size async canvasToTempFilePathFunc(cvWidth, cvHeight, qrCanvas) { try { let res = await canvasToTempFilePath( cvWidth, cvHeight, qrCanvas); this.setData({ canvasTempFilePath: res.tempFilePath }); } catch (error) { console.log(error); util.showToast(error.errMsg); } }, // Save the image to local async saveImageToPhotosAlbumFunc( ) { try { let res = await saveImageToPhotosAlbum(this.data.canvasTempFilePath); console.log(res); this.hideCanvas(); util.showToast('Image saved successfully'); } catch (err) { console.log(err); } }})The writing is relatively simple, because it is mainly for the convenience of myself to record, so it does not take into account too many usage scenarios.
SummarizeThe above is the html5 canvas drawing of the WeChat applet introduced by the editor and saved to the system album. I hope it will be helpful to you. If you have any questions, please leave me a message and the editor will reply to you in time!