“This article has participated in the good article call order activity, click to see: back end, big front end double track submission, 20,000 yuan prize pool for you to challenge!”
序
It is boring to always learn knowledge points, so do a small chestnut to relieve the fatigue of learning it (more tired)
I also talked about making a calculator in my learning small program video tutorial, but the calculator in the tutorial is so crude that I can only do some calculations. No, men need to be persistent.
Win10, win10, win10, win10, win10, win10, win10, win10, win10, win10, win10, win10, win10, win10, win10, win10, win10, win10, win10
Realized effect (the picture was not recorded completely, the right side is missing a bit) :
The text start
WeChat development documentation: developers.weixin.qq.com/miniprogram…
Create the page
In wechat small program, page is a very important concept. Calculator page can be generated by right-clicking in the resource manager to create a folder, or directly by entering the page address and name in the page object of app.json.
Here’s an example from app.json:
"pages": [
"pages/Calculator/Calculator"."pages/index/index"."pages/logs/logs",].Copy the code
CTRL + S saves, and the Calculator page appears in Explorer
When the page is first created, it has only one line in WXML, so just delete it.
The navigationBarTitleText text and background color of the top title bar can be set in app.json or in the JS (Calculator.js) of the page
- Set in app.json
- The Calculator. Js set in
onLoad() {
wx.setNavigationBarTitle({
title: Empty City Machine by Calculator,
})
wx.setNavigationBarColor({
frontColor: '#ffffff'.backgroundColor: '#C37D58',}}),Copy the code
The page layout
In this production, in order to adapt to different models, I use the size format is RPX. The model is iPhone6, so 1px == 2rpx, the CSS written px pixel size by 2
The overall page is divided into three large, background, screen, buttons
I used the image tag for the background, which is absolutely positioned at 100% size
On the screen, I wanted to make a toolbar, but I gave up for now
The screen is currently divided into a calculation bar and a result bar
The key interface is divided into three parts: one is the function of clearing, positive and negative numbers, and taking mod; one is the function of adding, subtracting, multiplying and dividing the five keys; the other is the part of the number keys
Here is:
The page style
The style of the page is concentrated in the WXSS file
The screen and buttons have a ground-glass effect, which blurs out the background image at the bottom
The ground-glass effect was made mainly by background-color translucent color, and then backdrop filter blur effect was set
The MDN for the Sydari-filter is developer.mozilla.org/zh-CN/docs/…
Here you can choose your own colors, such as my screen CSS:
background-color: rgba(255.255.255.3); /* Background color */
box-shadow: 6rpx 6rpx 12px 6rpx rgba(0.0.0.3); / * * / shadow
backdrop-filter: blur(20rpx); /* Gaussian filter */
Copy the code
For the keyboard layout I used the Flex layout, which worked very well. I set the top keys to 25% wide and let flex-wrap: wrap; The wrap is in effect, and the keys are effectively laid out.
In setting up0 keys
When using:nth-child
You can select the subclass
In the click of the keyboard keys, keys need to have a dynamic interaction process, in the micro channel small program has a concept of hover class, hover class can be attached to a class on the view, the class style is the style of the key pressed, usually after the finger raised, The duration of this style is 400 milliseconds, which can be set using hohover stay-time
By the way, even in WXSS, there is still :hover, but this time :hover is set to press down the style, and the finger does not recover oh
Data rendering
On the keyboard below the calculator, there are 19 keys, and it would be too tedious to write one key at a time into WXML, and it would be a hassle to write click methods
So I write the information about these buttons to a JS file. In Page(), there is data, which is the initial data set of the Page. In the keysData array object, there is an array of keys, each of which has name, index and type properties. The type attribute can be used to distinguish between an operator and a number
/** * page initial data */
data: {
keysdata: [ // type: 0 operator 1 number
{ name: 'AC'.index: '001'.type: 0 },
{ name: '+ / -.index: '002'.type: 0 },
{ name: The '%'.index: '003'.type: 0 },
{ name: 'present'.index: '004'.type: 0 },
{ name: '7'.index: '005'.type: 1 },
{ name: '8'.index: '006'.type: 1 },
{ name: '9'.index: '007'.type: 1 },
{ name: The '*'.index: '008'.type: 0 },
{ name: '4'.index: '009'.type: 1 },
{ name: '5'.index: '0010'.type: 1 },
{ name: '6'.index: '0011'.type: 1 },
{ name: The '-'.index: '0012'.type: 0 },
{ name: '1'.index: '0013'.type: 1 },
{ name: '2'.index: '0014'.type: 1 },
{ name: '3'.index: '0015'.type: 1 },
{ name: '+'.index: '0016'.type: 0 },
{ name: '0'.index: '0017'.type: 1 },
{ name: '. '.index: '0018'.type: 1 },
{ name: '='.index: '0019'.type: 0},].resultNum: '0'./ / the result
calNum1: ' '.// Calculate the front digit
calNum2: ' '.// Calculate the back bit
calIcon: ' './ / calculation
calIconEQ: ' '.// = The operator
isCompute: false.// Whether to calculate
lastbtn: 0.// The previous button 0: number 1: calculate symbol 2: equal to 3: clear 4: positive or negative
},
Copy the code
The wX :for statement is used in the WXML key rendering to iterate through the rendered keys
<view class="keyboards" wx:for="{{ keysdata }}" wx:key="index">
<view class="keys" data-num="{{ item }}" hover-class="hoverkeys"
hover-stay-time="100" bindtap="keyClick" >
{{ item.name }}
</view>
</view>
Copy the code
Calculation logic
This is the most complicated and difficult part of the whole process
At first, I didn’t add the attributes of the previous button, which made my initial judgment tired and incomplete
And then I rewrote the logic
Compute (num1, num2, way) = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = Way and num1 and num2 may pass num1 and num2 as empty strings. So you need to calculate the value depending on the method (you don’t want to put code in there)
compute(num1, num2, way) {
let res = 0;
switch(way) {
case The '%':
if(! num1 && num1 ! =0) { num1 = '1' }
if(! num2) { num2 ='1' }
res = parseFloat(num1) % parseFloat(num2); break;
case 'present':
if(! num1) { num1 ='1' }
if(! num2) { num2 ='1' }
res = parseFloat(num1) / parseFloat(num2); break;
case The '*':
if(! num1) { num1 ='1' }
if(! num2) { num2 ='1' }
res = parseFloat(num1) * parseFloat(num2); break;
case The '-':
if(! num1) { num1 ='0' }
if(! num2) { num2 ='0' }
res = parseInt(num1) - parseInt(num2); break;
case '+':
if(! num1) { num1 ='0' }
if(! num2) { num2 ='0' }
res = parseFloat(num1) + parseFloat(num2); break;
}
return res;
}
Copy the code
CalNum1, calNum2, calIcon and other objects defined by data in the above data rendering are needed in the calculation procedure bar and the result bar
<! -- Calculation process -->
<view class="calcuProcess">
{{ calNum1 }} {{ calIcon }} {{ calNum2 }} {{ calIconEQ }}
</view>
<! -- Results and inputs -->
<view class="inputNum">
{{ resultNum }}
</view>
Copy the code
calNum1 | calIcon | calNum2 | calInconEQ | resultNum |
---|---|---|---|---|
7 | + | 8 | = | 15 |
Since keyboard keys are rendered using Wx :for, data-num=”{{item}}” uses data- to bind key data to the element
So you can use bindTap =”keyClick” to bind the keyClick method to determine which key is being pressed based on the target of the event
let n = event.target.dataset.num;
First determine whether the key is a numeric key or a compute key
If it is a numeric key and the last pressed key is a calculator, set the value of the input resultNum in the result field to an empty string first, and then check whether the first letter is 0. If it is a number such as 08 or 012, remove the 0 from the first letter
1. Each key has its own logical method, entering different methods based on the key value
// Determine which method to execute
switch (n.name) {
case 'AC': this.clearScreen(); break;
case '+ / -: this.isNegative(); break;
case The '%': this.remainder(); break;
case 'present': this.division(); break;
case The '*': this.multiplication(); break;
case The '-': this.reduce(); break;
case '+': this.add(); break;
case '=': this.equalRes(); break;
}
Copy the code
The last button lastbTN is a number, then calNum1 is calculated with the current value displayed in the result column. For example: Let res = this.compute(data.calnum1, data.resultnum, ‘+’), calculate the data, then remove calNum2 and the last equal sign
If the procedure column is empty, press the operator directly, then it is
The difference between wechat applet and vue is that it is not two-way binding. Although using this.callcon = ‘some value’ can change the current calIncon, it does not change the WXML page. So you need to use the setData method to change the page
3, the current key value is equal sign to determine whether there is an equal sign in the calculation process column, if there is, then continue to calculate the value of calNum1 and the value of the result column as shown in the following example:
If calNum2 is not followed, determine if the last keystroke was a number or an equal sign
If the last key was a calculator
4. Clear character: set resultNum to 0, and set other symbols such as calNum1 to null
Note: here like the key of the logic is not specifically written, so you can diverge in writing, and my logic is not necessarily the optimal solution, can only say to you a general direction
The complete code
Calculator.wxml
<! -- Background -->
<image class="img" src=".. /.. /source/wei2.png"></image>
<! -- Screen part -->
<view class="calculateScreen">
<! -- Function bar -->
<view class="funBar"></view>
<! -- Calculation process -->
<view class="calcuProcess">
{{ calNum1 }} {{ calIcon }} {{ calNum2 }} {{ calIconEQ }}
</view>
<! -- Results and inputs -->
<view class="inputNum">
{{ resultNum }}
</view>
</view>
<! -- Keyboard Interface -->
<view class="keyboard">
<view class="keyboards" wx:for="{{ keysdata }}" wx:key="index">
<view class="keys" data-num="{{ item }}" hover-class="hoverkeys"
hover-stay-time="100" bindtap="keyClick" >
{{ item.name }}
</view>
</view>
</view>
Copy the code
Calculator.wxss
/* pages/Calculator/Calculator.wxss */
.img{
position: absolute;
top: 0rpx;
width: 100%;
height: 100vh;
z-index: 0;
}
.calculateScreen {
position: relative;
width: 100%;
height: 30vh;
background-color: rgba(255.255.255.3);
z-index: 100;
box-shadow: 6rpx 6rpx 12px 6rpx rgba(0.0.0.3);
overflow: hidden;
/ * applet gaussian blur effect to add backdrop * /
backdrop-filter: blur(20rpx);
}
.funBar {
width: 100%;
height: 90rpx;
}
.calcuProcess {
width: 100%;
height: 90rpx;
line-height: 90rpx;
font-size: 32rpx;
text-align: right;
color: #1d1a1a;
}
.inputNum {
width: calc(100vw - 40rpx);
height: calc(100% - 200rpx);
line-height: 115rpx;
font-size: 80rpx;
text-align: right;
padding: 0rpx 20rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-shadow: 5px 5px 5px # 464443;
}
.keyboard {
width: 100%;
height: calc(70vh - 32rpx);
padding-top: 12rpx;
display: flex;
flex-wrap: wrap;
position: relative;
}
.keyboards {
width: 25%;
height: 20%;
display: flex;
justify-content:center;
align-items: center;
}
.keys {
width: 130rpx;
height: 130rpx;
border-radius: 50%;
line-height: 130rpx;
text-align: center;
font-size: 60rpx;
backdrop-filter: blur(10px);
/ * background - color: rgba (246245245, 6); * /
background: linear-gradient(145deg.rgba(235.228.228.3), rgba(221.214.214.2));
box-shadow: 10px 10px 20px #8d8888,
-10px -10px 20px #e2dfdf;
color: #fff;
text-shadow: 5px 5px 5px # 992002;
}
.hoverkeys {
background: linear-gradient(145deg.rgba(221.214.214.6), rgba(235.228.228.7));
box-shadow: 10px 10px 30px #302a2a,
-10px -10px 30px # 726060;
}
.keyboards:nth-child(17) {
width: 50%;
}
.keyboards:nth-child(17) .keys {
width: 300rpx;
border-radius: 130rpx;
}
Copy the code
Calculator.js
// pages/Calculator/Calculator.js
Page({
onLoad() {
wx.setNavigationBarTitle({
title: Empty City Machine by Calculator,
})
wx.setNavigationBarColor({
frontColor: '#ffffff'.backgroundColor: '#C37D58',}}),/**
* 页面的初始数据
*/
data: {
keysdata: [ // type: 0 operator 1 number
{ name: 'AC'.index: '001'.type: 0 },
{ name: '+ / -.index: '002'.type: 0 },
{ name: The '%'.index: '003'.type: 0 },
{ name: 'present'.index: '004'.type: 0 },
{ name: '7'.index: '005'.type: 1 },
{ name: '8'.index: '006'.type: 1 },
{ name: '9'.index: '007'.type: 1 },
{ name: The '*'.index: '008'.type: 0 },
{ name: '4'.index: '009'.type: 1 },
{ name: '5'.index: '0010'.type: 1 },
{ name: '6'.index: '0011'.type: 1 },
{ name: The '-'.index: '0012'.type: 0 },
{ name: '1'.index: '0013'.type: 1 },
{ name: '2'.index: '0014'.type: 1 },
{ name: '3'.index: '0015'.type: 1 },
{ name: '+'.index: '0016'.type: 0 },
{ name: '0'.index: '0017'.type: 1 },
{ name: '. '.index: '0018'.type: 1 },
{ name: '='.index: '0019'.type: 0},].resultNum: '0'./ / the result
calNum1: ' '.// Calculate the front digit
calNum2: ' '.// Calculate the back bit
calIcon: ' './ / calculation
calIconEQ: ' '.// = The operator
isCompute: false.// Whether to calculate
lastbtn: 0.// The previous button 0: number 1: calculate symbol 2: equal to 3: clear 4: positive or negative
},
// Keyboard click event
keyClick(event) {
let n = event.target.dataset.num;
if (n.type == 1) {
if (this.data.lastbtn == 1) {
this.data.resultNum = ' '
}
if (this.data.resultNum == '0') {
if(n.name ! ='. ')
this.data.resultNum = n.name;
else
this.data.resultNum += n.name;
} else {
if( this.data.lastbtn == '2' ) {
// Whether it is equal to pass
if (this.data.calIconEQ) {
this.clearScreen();
}
this.data.resultNum = ' ';
}
this.data.resultNum += n.name;
}
this.setData({ resultNum: this.data.resultNum })
this.data.lastbtn = 0; // Update the latest by pressing the button
} else if(n.type == 0) {// Determine which method to execute
switch (n.name) {
case 'AC': this.clearScreen(); break;
case '+ / -: this.isNegative(); break;
case The '%': this.remainder(); break;
case 'present': this.division(); break;
case The '*': this.multiplication(); break;
case The '-': this.reduce(); break;
case '+': this.add(); break;
case '=': this.equalRes(); break; }}},/ / add
add () {
let data = this.data;
if (data.lastbtn == 1 && data.calIcon == '+') return ;
// Last number
if (data.lastbtn == 0) {
let res = this.compute(data.calNum1, data.resultNum, '+')
this.setData({ calNum1: res })
this.setData({ resultNum: res })
}
// last time was equal to
if (data.lastbtn == 2 && data.calIconEQ) {
this.setData({ calNum1: data.resultNum })
this.setData({ calNum2: ' ' })
this.setData({ calIconEQ: ' '})}// If the interface is empty
if(! data.calNum1 && ! data.calIcon) {this.setData({ calNum1: data.resultNum });
}
this.setData({ calIcon: '+' });
data.lastbtn = 1; // Update the latest by pressing the button
},
/ / remove
clearScreen () {
this.setData({ resultNum: '0' });
this.setData({ calNum1: ' ' });
this.setData({ calNum2: ' ' });
this.setData({ calIcon: ' ' });
this.setData({ calIconEQ: ' ' });
this.data.lastbtn = 3; // Update the latest by pressing the button
console.clear()
},
/ / plus or minus
isNegative (){
let data = this.data;
data.resultNum = parseFloat(data.resultNum); // The value is a string
if (data.resultNum > 0) {this.setData({ resultNum: -data.resultNum })
} else {
this.setData({ resultNum: Math.abs(data.resultNum) })
}
data.lastbtn = 4; // Update the latest by pressing the button
},
/ / remainder
remainder () {
let data = this.data;
if (data.lastbtn == 1 && data.calIcon == The '%') return ;
// Last number
if (data.lastbtn == 0) {
if(! data.calNum1 && ! data.calIcon) {this.setData({ calNum1: data.resultNum })
} else {
let res = this.compute(data.calNum1, data.resultNum, The '%')
this.setData({ calNum1: res })
this.setData({ resultNum: res })
}
}
// last time was equal to
if (data.lastbtn == 2 && data.calIconEQ) {
this.setData({ calNum1: data.resultNum })
this.setData({ calNum2: ' ' })
this.setData({ calIconEQ: ' '})}// If the interface is empty
if(! data.calNum1 && ! data.calIcon) {this.setData({ calNum1: data.resultNum });
}
this.setData({ calIcon: The '%' });
data.lastbtn = 1; // Update the latest by pressing the button
},
/ / division
division () {
let data = this.data;
if (data.lastbtn == 1 && data.calIcon == 'present') return ;
if (data.calIconEQ) {
}
// Last number
if (data.lastbtn == 0) {
if(! data.calNum1 && ! data.calIcon) {this.setData({ calNum1: data.resultNum })
} else {
let res = this.compute(data.calNum1, data.resultNum, 'present')
this.setData({ calNum1: res })
this.setData({ resultNum: res })
}
}
// last time was equal to
if (data.lastbtn == 2 && data.calIconEQ) {
this.setData({ calNum1: data.resultNum })
this.setData({ calNum2: ' ' })
this.setData({ calIconEQ: ' '})}// If the interface is empty
if(! data.calNum1 && ! data.calIcon) {this.setData({ calNum1: data.resultNum });
}
this.setData({ calIcon: 'present' });
data.lastbtn = 1; // Update the latest by pressing the button
},
/ / the multiplication
multiplication () {
let data = this.data;
if (data.lastbtn == 1 && data.calIcon == The '*') return ;
// Last number
if (data.lastbtn == 0) {
let res = this.compute(data.calNum1, data.resultNum, The '*')
this.setData({ calNum1: res })
this.setData({ resultNum: res })
}
// last time was equal to
if (data.lastbtn == 2 && data.calIconEQ) {
this.setData({ calNum1: data.resultNum })
this.setData({ calNum2: ' ' })
this.setData({ calIconEQ: ' '})}// If the interface is empty
if(! data.calNum1 && ! data.calIcon) {this.setData({ calNum1: data.resultNum });
}
this.setData({ calIcon: The '*' });
data.lastbtn = 1; // Update the latest by pressing the button
},
/ / subtraction
reduce() {
let data = this.data;
if (data.lastbtn == 1 && data.calIcon == The '-') return ;
// Last number
if (data.lastbtn == 0) {
if(! data.calNum1 && ! data.calIcon) {this.setData({ calNum1: data.resultNum })
} else {
let res = this.compute(data.calNum1, data.resultNum, The '-')
this.setData({ calNum1: res })
this.setData({ resultNum: res })
}
}
// last time was equal to
if (data.lastbtn == 2 && data.calIconEQ) {
this.setData({ calNum1: data.resultNum })
this.setData({ calNum2: ' ' })
this.setData({ calIconEQ: ' '})}// If the interface is empty
if(! data.calNum1 && ! data.calIcon) {this.setData({ calNum1: data.resultNum });
}
this.setData({ calIcon: The '-' });
data.lastbtn = 1; // Update the latest by pressing the button
},
/ / the result
equalRes() {
let data = this.data;
let res;
// Check whether it is equal to pass
if (data.calIconEQ) {
res = this.compute(data.calNum1, data.calNum2, data.calIcon);
this.setData({ calNum1: res })
this.setData({ resultNum: this.compute(res, data.calNum2, data.calIcon) })
} else {
if (data.lastbtn == 2) return ;
// Check whether the latter number exists
if (this.data.calNum2) {} else {
if (data.lastbtn == 3) {
this.setData({ calNum1: data.resultNum })
this.setData({ calIcon: '=' });
}
if (data.lastbtn == 0 || data.lastbtn == 4) {
if(data.calIcon && data.calIcon ! ='=') {
res = this.compute(data.calNum1, data.resultNum, data.calIcon);
this.setData({ calNum2: data.resultNum });
this.setData({ calIconEQ: '=' });
this.setData({ resultNum: res });
} else {
this.setData({ calNum1: data.resultNum })
this.setData({ calIcon: '='}); }}if (data.lastbtn == 1) {
// console.log(data.resultNum)
this.setData({ calNum1: data.resultNum })
res = this.compute(data.calNum1, data.resultNum, data.calIcon);
this.setData({ calNum2: data.resultNum })
this.setData({ resultNum: res })
this.setData({ calIconEQ: '=' });
}
}
}
data.lastbtn = 2; // Update the latest by pressing the button
},
compute(num1, num2, way) {
let res = 0;
switch(way) {
case The '%':
if(! num1 && num1 ! =0) { num1 = '1' }
if(! num2) { num2 ='1' }
res = parseFloat(num1) % parseFloat(num2); break;
case 'present':
if(! num1) { num1 ='1' }
if(! num2) { num2 ='1' }
res = parseFloat(num1) / parseFloat(num2); break;
case The '*':
if(! num1) { num1 ='1' }
if(! num2) { num2 ='1' }
res = parseFloat(num1) * parseFloat(num2); break;
case The '-':
if(! num1) { num1 ='0' }
if(! num2) { num2 ='0' }
res = parseInt(num1) - parseInt(num2); break;
case '+':
if(! num1) { num1 ='0' }
if(! num2) { num2 ='0' }
res = parseFloat(num1) + parseFloat(num2); break;
}
returnres; }})Copy the code