Wechat applets
For micro channel small program development entry, or relatively simple, only need to have basic CSS + JS knowledge can, the cost is relatively low. After writing small programs and RN, there is a feeling that the original is very cumbersome, that is, small programs or RN and other new development methods really have a relatively large advantage in efficiency, the only disadvantage is the running speed (Canvas will have such a feeling). I feel that the types of front-end development (including mobile terminal) I am currently exposed to are basically the same routine: UI, network, data storage, rich text, pictures/videos. This article is from these several directions to sum up their own small program development experience.
Introduction to small procedures
In fact, small program development process has been to view the document, according to the document to operate. The usual process is to start with a simple tutorial. After that, look at the components. Then you can try to write requirements, and in the process, start looking up apis and frameworks.
Multiple columns list
During development, there was a requirement to implement an Android-like GridView grid list. However, wechat does not provide such a component, but the small program is similar to the HTML/CSS front end, it can be specified by specifying display:flex, then go to flex-wrap:wrap. For example, there is an array data: [” A “, “B”, “C”, “D”, “E”, “F”, “G”, “H” and “I” and “J”, “K”, “L”, “M”, “N”] need to display A list of three columns, can be dealt with as follows:
//GridPage.wxml
<view class='grid-container'>
<view wx:for="{{data}}" wx:key="{{item}}" class="grid-list">
<view class='grid-item'>
<text class='grid-item-text'>{{item}}</text>
</view>
</view>
</view>
//GridPage.wxss
Page {
min-height: 100%;
background-color: #fff;} .grid-container { margin-left: 4rpx; margin-right: 4rpx; display: flex; flex-wrap: wrap; flex-direction: row; }. Grid-list {width: 33.33%; } .grid-item { margin: 2rpx; background:# 999;
display: flex;
justify-content: center;
align-items: center;
}
.grid-item-text {
color: black;
}
Copy the code
In grid-Container, flex-wrap is wrap, and the direction is row. Then each of his items is 33.33% wide. Note that the external contanier must be set, not the internal list.
Hierarchical layout
In CSS, you need to use a hierarchical layout, which is similar to the Android FrameLayout effect. You can use z-index, or you can use an absolute location. For example, we have a requirement: below is an image, above is text.
//PositionPage.wxml
<view class='root'>
<image src='https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3756982450, & FM 27 & gp = = 0. 995202616 JPG' class='image'></image>
<text class='text'</text> </view> // positionPage.wcss. root{align-items: center; display: flex; flex-direction: column; position: relative; } .image{ width: 300rpx; height: 300rpx; } .text{ background-color:# 999;
position: absolute;
}
Copy the code
There are two main points: the position of the parent layout must be relative, and its position must be absolute.
Network request
The applet’s network request uses the wx.request() method, but it’s too bloated and not as compact as Promise. Fortunately, the applet supports Promise, so we can wrap HTTP around it and make it organized. At this point, you need to pay attention to the wechat background configuration of various request domain name, upload domain name, downloadFIle domain name. The following encapsulated examples return data in JSON format as a POST request:
// Actually initiate the requestfunction _request(url, param) {
if (isDebug) {
Log.i("http==> params->" + JSON.stringify(param));
Log.i("http==> url->" + url);
}
return new Promise((resolve, reject) => {
wx.request({
url: url,
data: param,
header: {
'content-type': 'application/json'."Accept": "application/json"
},
method: "POST",
success: function (response) {
if (isDebug) {
const jsonResponse = JSON.stringify(response);
Log.i("http==> response->" + jsonResponse);
}
const {data, statusCode, ok = false} = response; // Only ok is allowedtrueData does not necessarily contain dataif (statusCode === 200 && data && data.ok) {
resolve(data, ok);
} else {
if(statusCode ! = 404 && statusCode < 500 && statusCode > 300) { ToastUtil.showError(); } reject(data); } }, fail: reject }); }); }Copy the code
Use:
function getInfo(fid) {
const params = {};
params.token = user.token;
params.uid = user.uid;
return _request("INFO_URL", params);
}
Copy the code
You can then call that method when you need to make a request, processing the Promise.
Upload pictures to Aliyun
It should be noted that the configuration of wechat Upload interface cannot directly configure the URL of Aliyun at present. Aliyun should bind with our domain name first, and then set it in the upload interface of wechat background. You can refer to blog: small program picture upload ali OSS use method, obtain the signature Ali cloud Demo address: JavaScript client signature direct upload, through the log to obtain policy and signature (signature time can be slightly set a little longer), then began to package the upload method. As follows:
/** * Real upload code */function _upload(file, success, fail) {
const suffix = file.substring(file.lastIndexOf(".")); Const fileName = hex_md5(file); Log.i("fileName=" + (fileName + suffix));
wx.uploadFile({
url: ALIYUNPHOTOADDRESS,
formData: {
"OSSAccessKeyId": "Your AliYun accessKey"."key": DIR+ (fileName + suffix),
"policy": "Your policy"."success_action_status": '200'."signature": "你的signature"
},
filePath: file,
name: 'file',
success: function (res) {
const {statusCode} = res;
if (statusCode === 200) {
console.log(JSON.stringify(res));
success("" + fileName + suffix);
} else {
console.log("Upload failed");
fail(res);
}
},
fail: function (e) {
fail(e);
console.log("Upload failed");
console.log("e=" + JSON.stringify(e));
}, complete: function () {
console.log("Upload process completed"); }}}})Copy the code
Where URL is the address of OOS upload, key is the folder to upload + the file name after upload. Here fileName is calculated by an MD5 to ensure uniqueness and no special characters. The MD5 algorithm comes from JS-MD5 encryption.
We can incidentally encapsulate a method for uploading multiple images, and use Promise to return:
/** * files Files to be uploaded, is an array, which is the absolute path of the file */function uploadFiles(files) {
if(! files || files.length <= 0) { wx.showModal({ title:'Picture error',
content: 'Please try again',
showCancel: false});return Promise.reject();
}
Log.i("Start uploading" + files);
returnNew Promise((resolve, reject) => {// Name of the uploaded filelet uploadPaths = [];
for (leti = 0; i < files.length; I ++) {_upload(files[I], (path) => {// uploadPaths[uploadPaths.if(uploadpaths.length >= files.length) {// Return resolve([ALIYUNPHOTOADDRESS +]"/"+DIR, uploadPaths]); } }, () => { //error reject(res); }); }});Copy the code
Canvas use
- Because we need to use Canvas to draw a tree, there are many pits here. My requirement is Canvas full screen, besides drawing a tree, I also need to draw some other independent buttons. First, to set the Canvas to full screen and non-sliding, you can do the following:
<canvas disable-scroll='true' style="width: {{width}}px; height: {{height}}px; background-color:#efeff4; flex:1;" canvas-id="canvas" bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd"></canvas>
Copy the code
- When disable-scroll is set to true, three touch events need to be bound to respond to the touch event of the canvas. Where width+height is obtained by wx.getSystemInfo().
- Second, canvas has no catchtap events like View, only touch events, see canvas for details
- However, Canvas is of the highest level in wechat miniprogram and cannot be adjusted by setting z-index. Therefore, if your Canvas is full screen and you need some other buttons, you can only draw with the last Canvas.
- To draw a line using moveTo+lineTo on canvas, you need to call Canvas.beginPath () first and then canvas.closepath () after drawing.
c.beginPath();
c.setLineWidth(this.arrowPaint.width);
c.setStrokeStyle(this.arrowPaint.color);
c.setLineCap("square");
c.moveTo(this.arrowStartPointF.x, this.arrowStartPointF.y);
c.lineTo(this.arrowCenterPointF.x, this.arrowCenterPointF.y);
c.moveTo(this.arrowCenterPointF.x, this.arrowCenterPointF.y);
c.lineTo(this.arrowEndPointF.x, this.arrowEndPointF.y);
c.stroke();
c.closePath();
Copy the code
- When drawing multiple images/lines in a row, do not call draw(true) multiple times in a row, which will cost performance. Normally, call fill()/stoke() as the last method. Such as
// Draw the point c.beguinpath ();let y = node.noteView.pointFrameCenter.y + Constant.FRAME_HEIGHT / 2 + Constant.GAP_BETWEEN_DOT + Constant.RADIUS_DOT;
c.setFillStyle(Constant.LINE_COLOR_RED);
c.setLineWidth(Constant.LINE_WIDTH);
c.arc(node.noteView.pointFrameCenter.x, y, Constant.RADIUS_DOT, 0, 2 * Math.PI);
//
y += (Constant.GAP_BETWEEN_DOT + Constant.RADIUS_DOT);
c.arc(node.noteView.pointFrameCenter.x, y, Constant.RADIUS_DOT, 0, 2 * Math.PI);
//
//
y += (Constant.GAP_BETWEEN_DOT + Constant.RADIUS_DOT);
c.arc(node.noteView.pointFrameCenter.x, y, Constant.RADIUS_DOT, 0, 2 * Math.PI);
c.fill();
c.closePath();
Copy the code
- For the draw method, it is recommended to just call draw(), do not call draw(true), draw(true) on the original canvas, will not empty the old canvas, draw() will empty. Draw () : / / draw(true) : / / draw(true) : / / draw(true) : / / draw(true) : / / draw(true) : / / draw(true) : / / draw(true) : / / draw(true) : / / draw(true) : / / draw(true) : / / draw(true) : / / draw(true) And the next time you go to reDraw, you don’t have to empty the canvas first.
- Canvas follow drag gesture
//index.wxml
<canvas disable-scroll='true' style="width: {{width}}px; height: {{height}}px; background-color:#efeff4;" canvas-id="canvas" bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd"></canvas>
//index.wcss
Page {
overflow: hidden;
display: flex;
}
//index.js
const app = getApp()
Page({
data: {
width: 0,
height: 0,
},
onLoad: function (e) {
this.time = (new Date()).valueOf();
this.x = 0;
this.y = 0;
this.moveX = 0;
this.moveY = 0;
const that = this;
wx.getSystemInfo({
success: function (res) {
that.setData({ width: res.screenWidth, height: res.screenHeight })
},
})
const ctx = wx.createCanvasContext("canvas", this)
this.canvas = ctx;
},
onReady: function () {
this.draw();
},
draw: function () {
this.canvas.fillRect(10, 10, 150, 100)
this.canvas.fill();
this.canvas.draw()
},
touchMove: function (e) {
console.log("touchMove")
let xOffset = e.touches[0].x - this.x;
let yOffset = e.touches[0].y - this.y;
this.x = e.touches[0].x;
this.y = e.touches[0].y;
this.moveX = this.moveX + xOffset;
this.moveY = this.moveY + yOffset;
this.canvas.translate(this.moveX, this.moveY);
this.draw();
},
touchStart: function (e) {
this.x = e.touches[0].x;
this.y = e.touches[0].y;
},
touchEnd: function (e) {
console.log("touchEnd")}})Copy the code
Other scale and other methods are similar.