微信小程序开发—— 制作一款好看的计算器

Posted 空城机

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了微信小程序开发—— 制作一款好看的计算器相关的知识,希望对你有一定的参考价值。

微信小程序总是学习知识点也是很枯燥的,那么就做个小栗子来缓解一下学习的疲倦吧(更累了)

像我学习小程序视频教程中也有说过做计算器,不过教程中的计算器太粗糙了,只能计算一下就结束了。 这可不行,男人要持久🐶

所以我有感而发,准备做一个完整度高一些的简单计算器,计算器的基本功能就模仿win10自带的计算器吧,有加、减、乘、除、取余、正负这几块的功能,界面自己进行一下调整。

实现效果(图居然没录全,右侧少了一点):
在这里插入图片描述



正文开始

微信开发文档:https://developers.weixin.qq.com/miniprogram/dev/component/


创建页面

在微信小程序中,page页面是一个非常重要的概念,计算器页面可以在资源管理器中自己右键创建文件夹生成,也可以直接在app.json的page对象中输入页面地址和名称来生成。

app.json中例子如下:

"pages": [
    "pages/Calculator/Calculator",
    "pages/index/index",
    "pages/logs/logs",
],

ctrl + s保存后,资源管理器中就出现了Calculator的页面

在这里插入图片描述
页面一开始创建出来,在wxml中只有一行字,直接删掉即可。

关于navigationBarTitleText顶部标题栏的文字和背景颜色,可以在app.json中设置,也可以在页面的JS(Calculator.js)中进行设置

  • 在app.json中设置

在这里插入图片描述

  • Calculator.js中设置
onLoad() {
   wx.setNavigationBarTitle({
        title: '空城机の计算器',
    })
    wx.setNavigationBarColor({
        frontColor: '#ffffff',
        backgroundColor: '#C37D58',
    })
},

在这里插入图片描述



页面布局

在本次制作当中,为了在不同机型下自适应,我使用的尺寸格式是rpx,机型选择了iPhone6,这样 1px == 2rpx,将CSS编写的px像素大小乘2即可

页面总体分为三大块, 背景、屏幕、按键

背景我使用了image标签来做的,绝对定位,大小100%

在屏幕上,本来我想制作一条工具栏,暂时先放弃了

屏幕上目前分为计算栏和结果栏

按键界面上分为三块,一块是清除、数字正负、取余功能,一块是加减乘除等于这5个按键,另一块是数字按键部分

图示:
在这里插入图片描述



页面样式

页面的样式主要集中在wxss文件当中

屏幕和按键都是以毛玻璃效果为主,这样可以将底部的背景图模糊的展现出来

毛玻璃效果的制作以背景色background-color半透明为主,然后设置backdrop-filter blur滤镜模糊效果

backdrop-filter的MDN:https://developer.mozilla.org/zh-CN/docs/Web/CSS/backdrop-filter

这里的颜色大家可以自己自由选择搭配,比如我的屏幕CSS:

background-color: rgba(255, 255, 255, .3);  /* 背景色 */
box-shadow: 6rpx 6rpx 12px 6rpx rgba(0, 0, 0, .3);  /* 阴影 */
backdrop-filter: blur(20rpx);  /* 高斯滤镜 */

键盘的按键布局我使用了flex布局,这款布局非常好用,将上面的按键设置为宽25%,让flex-wrap: wrap;自动换行生效,按键就可以有效的排版布局了。

在设置0按键时,使用:nth-child子类选择即可
在这里插入图片描述

在点击键盘按键时,按键需要有一个动态的交互过程,在微信小程序中有一个hover-class的概念,在view上可以给hover-class附上一个class,这个class的样式就是按键按下时的样式,通常手指抬起后,这个样式的持续时间有400毫秒,这里可以使用hover-stay-time设置一个时间

顺便提一句,即使是在wxss中,依旧还是有:hover的存在,不过此时的:hover设置的就是按下去的样式,并且手指抬起不会恢复哦

在这里插入图片描述



数据渲染

在计算器下方的键盘上,按键有19个,如果一个按键一个按键写入wxml当中,就未免太过繁琐了,而且写点击方法时也比较麻烦

所以我将这些按钮的信息写入JS文件中,在Page()中存在data,这是页面的初始数据
设置keysdata数组对象,里面装了按键数组,每个按键都有name、index、type这三个属性。 type属性可以用来区分到底是计算符还是数字

/**
* 页面的初始数据
*/
data: {
   keysdata: [  // type:0 计算符  1 数字
       { name: 'AC', index: '001', type: 0 },
       { name: '+/-', index: '002', type: 0 },
       { name: '%', index: '003', type: 0 },
       { name: '÷', index: '004', type: 0 },
       { name: '7', index: '005', type: 1 },
       { name: '8', index: '006', type: 1 },
       { name: '9', index: '007', type: 1 },
       { name: '×', index: '008', type: 0 },
       { name: '4', index: '009', type: 1 },
       { name: '5', index: '0010', type: 1 },
       { name: '6', index: '0011', type: 1 },
       { name: '-', 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',  //结果
   calNum1: '',  // 计算前位
   calNum2: '',  // 计算后位    
   calIcon: '',  // 计算符   
   calIconEQ: '',  // = 计算符   
   isCompute: false,  // 是否计算
   lastbtn: 0,  //上一个按钮  0:数字  1:计算符号  2:等于 3:清空 4:正负
},

在wxml的按键渲染中使用wx:for语句遍历渲染出按键

<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>


计算逻辑

这是整个过程中最复杂最困难的部分

一开始我并没有添加记录上一个按键的属性,这导致了我一开始的判断做的很累,而且还不完善

然后又把逻辑给重新写了一下

在按键按下去的功能中,最重要的是计算和等于两种
计算中按键判断大致相同,首先先准备一个计算方法compute,根据传入参数将加减乘除取余这五种操作写入进去
compute(num1, num2, way)参数有三个,前两个代表计算的数值,way表示方式
并且num1和num2因为判断的不同,可能传入的num1,num2数值会是空字符串。所以需要将数值根据方法不同来进行计算 (本来不想放代码的)

compute(num1, num2, way) {
    let res = 0;
    switch(way) {
        case '%':
            if (!num1 && num1 != 0) { num1 = '1' }
            if (!num2) { num2 = '1' }
            res = parseFloat(num1) % parseFloat(num2); break;
        case '÷':
            if (!num1) { num1 = '1' }
            if (!num2) { num2 = '1' }
            res = parseFloat(num1) / parseFloat(num2); break;
        case '×': 
            if (!num1) { num1 = '1' }
            if (!num2) { num2 = '1' }
            res = parseFloat(num1) * parseFloat(num2); break;
        case '-': 
            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;
}

在计算过程栏和结果栏中需要用到上面数据渲染中data定义的calNum1、calNum2、calIcon等对象

 <!-- 计算过程 -->
 <view class="calcuProcess">
  {{ calNum1 }} {{ calIcon }} {{ calNum2 }} {{ calIconEQ }}
 </view>
 <!-- 结果和输入 -->
 <view class="inputNum">
   {{ resultNum }}
 </view>

在这里插入图片描述

calNum1calIconcalNum2calInconEQresultNum
7+8=15

因为键盘按键是使用wx:for进行渲染的,data-num="{{ item }}"利用data-将按键数据绑定到元素上

所以可以使用bindtap="keyClick"来绑定keyClick点击方法
根据event的target来判断当前按下的是哪一个按键

let n = event.target.dataset.num;

先判断按键是否为数字按键或者是计算符按键

如果是数字按键,如果上一次按下的按键是计算符,那么结果栏的输入显示的resultNum数值先置为空字符串,之后再判断首字母是否是0,如果是08、012这类数字,将首字母的0去掉

如果按下的是计算符按键,那么判断就更加复杂了
1、每一种按键都有自身的逻辑方法,根据按键值进入不同的方法

// 判断执行哪个方法
switch (n.name) {
    case 'AC': this.clearScreen(); break;
    case '+/-': this.isNegative(); break;
    case '%': this.remainder(); break;
    case '÷': this.division(); break;
    case '×': this.multiplication(); break;
    case '-': this.reduce(); break;
    case '+': this.add(); break;
    case '=': this.equalRes(); break;
}        

2、当前按键值是加减乘除这类计算值
上一次的按键lastbtn为数字,那么将calNum1和结果栏上当前显示的数值进行计算
比如:let res = this.compute(data.calNum1, data.resultNum, '+')
上一次按键为等号 = ,将数据计算出来,然后去除calNum2和最后的等号
在这里插入图片描述
如果计算过程栏为空,直接按计算符,那么就是
在这里插入图片描述
最后不要忘记改变上一次的按键lastbtn记录和calIcon计算符
微信小程序和vue的区别在于这不是双向绑定的,虽然使用this.callcon = '某个值'可以改变当前的calIncon,但是页面wxml上并不会改变,所以需要使用setData方法来进行改变页面

3、当前按键值是等于号
判断在计算过程栏中是否有过等于符,如果有,那么继续那calNum1的值和结果栏值进行计算
如下示例:
在这里插入图片描述
如果接下来没有calNum2,判断上一次按键是否是数字或者等于符
在这里插入图片描述
如果上一次按键是计算符
在这里插入图片描述

4、清除符,将resultNum置为0,其他的calNum1等符号置为空即可
在这里插入图片描述


注意:这里像按键这些逻辑没有具体写,所以各位可以发散性的编写,并且我的逻辑并不一定是最优解,只能说给各位一个大致的方向



完整代码

Calculator.wxml

<!-- 背景图 -->
<image class="img" src="../../source/wei2.png"></image>
<!-- 屏幕部分 -->
<view class="calculateScreen">
  <!-- 功能栏 -->
  <view class="funBar"></view>
  <!-- 计算过程 -->
  <view class="calcuProcess">
   {{ calNum1 }} {{ calIcon }} {{ calNum2 }} {{ calIconEQ }}
  </view>
  <!-- 结果和输入 -->
  <view class="inputNum">
    {{ resultNum }}
  </view>  
</view>
<!-- 键盘界面 -->
<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>

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;
  /* 小程序的高斯模糊效果要加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(246,245,245, .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;
}

Calculator.js

// pages/Calculator/Calculator.js
Page({
    onLoad() {
        wx.setNavigationBarTitle({
            title: '空城机の计算器',
        })
        wx.setNavigationBarColor({
            frontColor: '#ffffff',
            backgroundColor: '#C37D58',
        })
    },
    /**
     * 页面的初始数据
     */
    data: {
        keysdata: [ // type:0 计算符  1 数字
            { name: 'AC', index: '001', type: 0 },
            { name: '+/-', index: '002', type: 0 },
            { name: '%', index: '003', type: 0 },
            { name: '÷', index: '004', type: 0 },
            { name: '7', index: '005', type: 1 },
            { name以上是关于微信小程序开发—— 制作一款好看的计算器的主要内容,如果未能解决你的问题,请参考以下文章

微信小程序需要哪些开发工具

微信小程序开发的完整流程介绍,新手必读

微信小程序开发之代码提示插件(VSCode)

微信小程序开发--模板(template)使用,数据加载,点击交互

来客推:微信小程序开发制作流程 简单4步搞清楚丨小程序开发

微信小程序开发之--"template模板“的应用