Wechat applet draws posters and saves photo albums
tip: The code uses uni’s api. If you use native WeChat applet development, you can replace uni with wx.
Article Directory
foreword
The article in this film is mainly to summarize and explain the functions that I actually use in my work and can be integrated.
1. How to use canvas
2. How to generate a picture after canvas drawing
3. Save the picture to the album
4.难点
How to solve the problem that the canvas level is higher than the position positioning level, and how to adapt to different screen size ratios
1. Analysis requirements
Two options:
- Enter the page to draw the canvas first, click the button to generate a picture and save the album
- Enter the page to draw the canvas first, and generate a picture, click the button to directly save the picture to the album
I am using the first method here, depending on actual needs. (actually not much difference)
2. Prepare data
Before starting to draw the canvas, first, analyze what content is used in the page:
- Background picture
- QR code picture
- Some descriptive text about the poster
Note:
1. Since these data may not be hard-coded content on the page, but are returned according to the api, it is necessary to prepare the data returned from the api before drawing the canvas.
2. Synchronization issues need to be considered
3. Start coding
First look at the page picture style
html part
<canvas :style="{height:pageHeight,width: _width +'px'}" canvas-id="mycanvas" />
<cover-view @tap="saveImg">
<cover-image src="btn_img.png"></cover-image>
</cover-view>
Parse:
1. First, you need to prepare a canvas to draw the content of the page. The id is the unique identifier.
2. You need a button to save the picture, but you can’t display the button on the upper layer of the canvas even if you use absolute positioning to adjust the level, so use the official Provided methods for overriding native components. cover-view
and cover-image
.
js part
Only the important parts of the code are mentioned here.
The variables used in the page can be modified by themselves, and the initial value of the variable can be an empty string
1. Start drawing after preparing the data
onReady() {
// 为了兼容不同机型页面大小,所以需要先获取到页面宽高
this.getSysInfo()
},
getSysInfo() {
/*获取手机宽高*/
let that = this
let imgUrl = this.imageUrl
let qrcodeUrl = this.codeUrl
uni.getSystemInfo({
success(res) {
console.log('屏幕宽度', res)
that._width = res.windowWidth
that._heigth = res.windowHeight
// 获取图片信息生成canvas
// 因为这里用的网络图片所以需要先获取本地网络图地址
that.getImginfo([imgUrl, qrcodeUrl], 0);
}
})
},
getImginfo(urlArr, _type) {
let that = this;
uni.getImageInfo({
src: urlArr[_type],
success: function(res) {
//res.path是网络图片的本地地址
if (_type === 0) {
//
that.localImageUrl = res.path
that.getImginfo(urlArr, 1)
} else {
//二维码
that.localCodeUrl = res.path
// 创建canvas图片
that.createNewImg();
}
},
fail: function(res) {
//失败回调
console.log('错误', _type, res)
}
});
},
createNewImg() {
let that = this;
let ctx = uni.createCanvasContext('mycanvas');
// 绘制背景
ctx.drawImage(this.localImageUrl, 0, 0, this._width, this._heigth - 44 - this.statusBarHeight);
// 绘制二维码区域
ctx.lineJoin = "round";
ctx.lineWidth = 12;
ctx.setFillStyle('#FFFFFF')
ctx.setStrokeStyle('#FFFFFF')
// 二维码区域y坐标
const yPosition = this._heigth - 44 - this.statusBarHeight - this.remSize(98) - 100
ctx.strokeRect(this.remSize(24), yPosition, this.remSize(326), this.remSize(98));
ctx.fillRect(this.remSize(24), yPosition, this.remSize(326), this.remSize(98));
// 绘制二维码
const yPosition2 = yPosition + 4
ctx.drawImage(this.localCodeUrl, this.remSize(28), yPosition2, this.remSize(90), this.remSize(90));
//二维码区域文字
let title1 = this.tips.title1;
let title2 = this.tips.title2;
let title3 = this.tips.title3;
// 文字一
ctx.setFontSize(this.remSize(14));
ctx.setFillStyle('#333333');
ctx.fillText(title1, this.remSize(128), yPosition + this.remSize(30));
// 文字二三
ctx.setFillStyle('#B8B8B8');
ctx.setFontSize(this.remSize(12));
ctx.fillText(title2, this.remSize(128), yPosition + this.remSize(62));
ctx.fillText(title3, this.remSize(128), yPosition + this.remSize(85));
// 绘制
ctx.draw();
//将生成好的图片保存到本地
uni.canvasToTempFilePath({
canvasId: 'mycanvas',
success: (res)=> {
that.loadImagePath = res.tempFilePath
},
fail: (res)=> {
console.log(res);
}
});
},
// 缩放比例
let scalePage = uni.getSystemInfoSync().windowWidth / 375
remSize(num) {
return num * scalePage
},
explain:
1. uni.createCanvasContext
Create a canvas context, which is used to operate and draw specific pictures and text.
2. ctx.drawImage
Used to draw pictures
. 3. ctx.setFillStyle
Used to draw fill colors
. 4. ctx.setStrokeStyle
Used to draw border colors
. It is the way of covering with rounded rectangles and solid rectangles, the effect is shown in the picture above.
6. ctx.strokeRect
Draw a hollow rectangle
7. ctx.fillRect
Draw a solid rectangle
6. ctx.setFontSize
ctx.setFillStyle
ctx.fillText
Draw the text size, color, and position
7. ctx.draw()
Draw all the context content on the canvas
. Special instructions:
- The remSize method is used to set the size of the image and the position ratio of the copy according to the design draft. Here, I calculate the ratio based on the width of 375 pixels.
- For the specific usage methods of these APIs, you can refer to the official documents, and I will not list them here.
2. Save the picture
//点击保存到相册
saveImg() {
uni.saveImageToPhotosAlbum({
filePath: this.loadImagePath,
success(res) {
uni.showToast({
title: '已保存到相册',
icon: 'success',
duration: 3000
})
}
})
},
Parse:
1. Because the save button is fixed in position, and the button is not drawn on the canvas, there is no button when saving the picture.
2. It should be noted that saving the photo album requires permission to save the photo album, which can be set by yourself in the document.
Summarize
For the coverage problem mentioned above, you can also use canvas to directly generate pictures, and then directly display the generated pictures on the page.
If there is any problem, please correct and modify.