当前位置:   article > 正文

微信小程序之计算器

微信小程序之计算器

在日常生活中,计算器是人们广泛使用的工具,可以帮助我们快速且方便地计算金额、成本、利润等。下面将会讲解如何开发一个“计算器”微信小程序。

一、开发思路

1、界面和功能

“计算器”微信小程序的页面效果如图所示

在计算器中可以进行整数和小数的加(+)、减(-)、乘(×)、除(÷)运算。“C”按钮为清除按钮,表示将输入的数字全部清空;“DEL”按钮为删除按钮,表示删除前面输入的一个数字;“+/-”按钮为正负号切换按钮,用于实现正负数切换;“.”按钮为小数点按钮,表示在计算过程中可以输入小数进行计算;“=”按钮为等号按钮,表示对输入的数字进行计算。

2、计算器设计数学原理

此计算器本本质是对数学表达式的求解,例如  Z=X+Y,其中,X,Y为两个自变量,Z为因变量,主要设计思路为千先输入X,Y,和"+"号,再输入“=”号计算结果并显示 。由此可知,基本操作为:

(1)输入第一个数字(存储为变量num1并显示)。

(2)输入运算符(存储为num2并显示)。

(3)输入运算符(形成表达式并显示)。

 (4)按下”=“(计算结果并显 示)。

3.  设计主要思路

根据以上分析可知,处理逻辑主要编写以下三个函数

        numBtn():处理函数三个数字按钮的事件处理函数

        opBtn:运算符按钮的事件处理函数

        execBtn():编写“=”按钮的事件处理函数

设计三个标识用以标识用户的三种状态,其中,数字改变标识为真:

numChangeFlag : 数字改变标识,第一数字和第二数字切换标识,初始值为false

execflag: 执行状态标识,初始值为false

resultflag: 结果状态标识,初始值为false

具体的处理逻辑详见四处理逻辑

二、界面设计

据以上的开发思路,界面分为显示区和按钮区,其中显示区又分为数字显示区、公式显示区两部分,上下排列;按钮可分为数字按钮,运算符按钮,功能按钮三部分,按钮显示区按四行四列显示,其中“0”独占两个单元格。代码如下所示:

  1. <!--index.wxml-->
  2. <navigation-bar title="计算器" back="{{false}}" color="black" background="#FFF"></navigation-bar>
  3. <!--结果区域-->
  4. <view class="result">
  5. <view class="result-num">{{num}}</view>
  6. <view class="result-sub">{{sub}}</view>
  7. </view>
  8. <!--按钮区域-->
  9. <view class="btns">
  10. <view>
  11. <view hover-class="bg" hover-stay-time="50" bindtap="resetBtn">C</view>
  12. <view hover-class="bg" hover-stay-time="50" bindtap="delBtn">DEL</view>
  13. <view hover-class="bg" hover-stay-time="50" bindtap="negBtn">+/-</view>
  14. <view hover-class="bg" hover-stay-time="50" bindtap="opBtn" data-val='×'>×</view>
  15. </view>
  16. <view>
  17. <view hover-class="bg" bindtap="numBtn" data-val="7">7</view>
  18. <view hover-class="bg" bindtap="numBtn" data-val="8">8</view>
  19. <view hover-class="bg" bindtap="numBtn" data-val="9">9</view>
  20. <view hover-class="bg" bindtap="opBtn" data-val="÷">÷</view>
  21. </view>
  22. <view>
  23. <view hover-class="bg" bindtap="numBtn" data-val="4">4</view>
  24. <view hover-class="bg" bindtap="numBtn" data-val="5">5</view>
  25. <view hover-class="bg" bindtap="numBtn" data-val="6">6</view>
  26. <view hover-class="bg" bindtap="opBtn" data-val="-">-</view>
  27. </view>
  28. <view>
  29. <view hover-class="bg" bindtap="numBtn" data-val="1">1</view>
  30. <view hover-class="bg" bindtap="numBtn" data-val="2">2</view>
  31. <view hover-class="bg" bindtap="numBtn" data-val="3">3</view>
  32. <view hover-class="bg" bindtap="opBtn" data-val="+">+</view>
  33. </view>
  34. <view>
  35. <view hover-class="bg" bindtap="numBtn" data-val="0">0</view>
  36. <view hover-class="bg" bindtap="dotBtn">.</view>
  37. <view hover-class="bg" bindtap="execBtn" data-val="=">=</view>
  38. </view>
  39. </view>

界面布置总体上采用“flex”流式布局column方式,上下排列,按钮区以每四个按钮为一组,共分四组,同样采用flex的流式布局,具体css代码如下所示:

  1. /**index.wxss**/
  2. page {
  3. display: flex;
  4. flex-direction: column;
  5. height: 100vh;
  6. color: #555;
  7. }
  8. .result {
  9. flex: 1;
  10. background: #f3fef6;
  11. position: relative;
  12. }
  13. .result-num {
  14. position: absolute;
  15. font-size: 15vw;
  16. bottom: 5vh;
  17. right: 3vw;
  18. }
  19. .result-sub{
  20. font-size: 10vw;
  21. position: absolute;
  22. bottom: 1vh;
  23. right: 3vw;
  24. }
  25. .btns {
  26. flex: 1;
  27. }
  28. /* 按钮样式 */
  29. .bg {
  30. background: #eee;
  31. }
  32. .btns {
  33. flex: 1;
  34. display: flex;
  35. flex-direction: column;
  36. font-size: 64rpx;
  37. border-top: 1rpx solid #ccc;
  38. border-left: 1rpx solid #ccc;
  39. }
  40. .btns > view {
  41. flex: 1;
  42. display: flex;
  43. }
  44. .btns > view > view {
  45. flex-basis: 25%;
  46. border-right: 1rpx solid #ccc;
  47. border-bottom: 1rpx solid #ccc;
  48. box-sizing: border-box;
  49. display: flex;
  50. align-items: center;
  51. justify-content: center;
  52. }
  53. .btns > view:last-child > view:first-child {
  54. flex-basis: 50%;
  55. }
  56. .btns > view:first-child > view:first-child {
  57. color: #f00;
  58. }
  59. .btns > view > view:last-child {
  60. color: #fc8e00;
  61. }

三,知识储备

1、data-*自定义属性

data-*是微信小程序的自定义属性,由data-前缀加上自定义的属性名,自定义属性值表示要传递的数据 ,在事件处理函数中通过targert或currentTarget对象的datasett属性获取数据

2、模块

微信小程序提供了模块化开发的语法,,使用module.exports语法对外暴露接口,然后在需要使用模块的地方通过require()函数引入 模块。

四、处理逻辑

1、数学处理模块

模块代码如下:

  1. // 精确计算
  2. module.exports = {
  3. target: 'num1', //表示当前正在输入哪个数字,取num1或num2
  4. num1: '0',
  5. num2: '0',
  6. op: '',
  7. // 重置
  8. reset() {
  9. this.num1 = '0'
  10. this.num2 = '0'
  11. this.target = 'num1'
  12. this.op = ''
  13. },
  14. changeNum2: function()
  15. {
  16. this.target='num2'
  17. },
  18. setNum: function(arg1){
  19. this[this.target]=arg1
  20. },
  21. getNum: function(){
  22. return this[this.target]
  23. },
  24. add: function(arg1, arg2) {
  25. var r1, r2, m
  26. try {
  27. r1 = arg1.toString().split(".")[1].length
  28. } catch (e) {
  29. r1 = 0
  30. }
  31. try {
  32. r2 = arg2.toString().split(".")[1].length
  33. } catch (e) {
  34. r2 = 0
  35. }
  36. m = Math.pow(10, Math.max(r1, r2))
  37. return (arg1 * m + arg2 * m) / m
  38. },
  39. sub: function(arg1, arg2) {
  40. var r1, r2, m, n
  41. try {
  42. r1 = arg1.toString().split(".")[1].length
  43. } catch (e) {
  44. r1 = 0
  45. }
  46. try {
  47. r2 = arg2.toString().split(".")[1].length
  48. } catch (e) {
  49. r2 = 0
  50. }
  51. m = Math.pow(10, Math.max(r1, r2))
  52. //动态控制精度长度
  53. n = (r1 >= r2) ? r1 : r2
  54. return ((arg1 * m - arg2 * m) / m).toFixed(n)
  55. },
  56. mul: function(arg1, arg2) {
  57. var m = 0,
  58. s1 = arg1.toString(),
  59. s2 = arg2.toString()
  60. try {
  61. m += s1.split(".")[1].length
  62. } catch (e) {}
  63. try {
  64. m += s2.split(".")[1].length
  65. } catch (e) {}
  66. return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m)
  67. },
  68. div: function(arg1, arg2) {
  69. var t1 = 0,
  70. t2 = 0,
  71. r1, r2
  72. try {
  73. t1 = arg1.toString().split(".")[1].length
  74. } catch (e) {}
  75. try {
  76. t2 = arg2.toString().split(".")[1].length
  77. } catch (e) {}
  78. r1 = Number(arg1.toString().replace(".", ""))
  79. r2 = Number(arg2.toString().replace(".", ""))
  80. return (r1 / r2) * Math.pow(10, t2 - t1)
  81. },
  82. // 进行运算
  83. getResult() {
  84. let result = 0
  85. if (this.op === '+') {
  86. result = this.add(this.num1, this.num2)
  87. } else if (this.op === '-') {
  88. result = this.sub(this.num1, this.num2)
  89. } else if (this.op === '×') {
  90. result = this.mul(this.num1, this.num2)
  91. } else if (this.op === '÷') {
  92. result =this. div(this.num1, this.num2)
  93. }
  94. return result
  95. }
  96. }

模块全局变量:

                target: 'num1',  //表示当前正在输入哪个数字,取num1或num2
                num1: '0',   //第一个操作数
                num2: '0',  //第二个操作数
                     op: '',  //操作符

模块函数:

        changeNum2():  //设置当前操作数为第二操作数

          setNum():    //设置操作数的值

         getNum():   //获取操作数的值

         getResult():  //获取计算结果

其它的 add,sub,mul,div分别为加、减、乘、除函数。

 2、计算器处理逻辑

  1. // index.js
  2. const calc = require('../../utils/calc.js')
  3. Page({
  4. /** 页面的初始数据 */
  5. data: {
  6. num: '0',
  7. op:''
  8. },
  9. //设置变量标识
  10. numChangeFlag : false,
  11. execflag: false,
  12. resultflag: false,
  13. //数字按钮的事件处理函数
  14. numBtn: function(e) {
  15. //点击数字按钮,获取对应的数字,将其值赋给num
  16. var num=e.target.dataset.val
  17. if(this.resultflag){
  18. this.resetBtn()
  19. }
  20. if(this.numChangeFlag){
  21. this.numChangeFlag=false
  22. this.execflag=true
  23. this.data.num='0'
  24. calc.changeNum2()
  25. }
  26. //设置输入的数字
  27. calc.setNum(this.data.num=='0'? num : this.data.num +num)
  28. //页面中显示数字
  29. this.setData({ num: calc.getNum() })
  30. },
  31. //运算符按钮处理函数
  32. opBtn: function(e){
  33. calc.op=e.target.dataset.val
  34. this.numChangeFlag=true
  35. //判断是否已输入第2个数字
  36. if(this.execflag){
  37. this.execflag=false
  38. //已经输入第2个数字,再判断是否有结果状态
  39. if(this.resultflag){
  40. this.resultflag=false
  41. } else {
  42. calc.num1=calc.getResult()
  43. }
  44. }
  45. this.setData({
  46. sub: calc.num1+' '+calc.op+' ',
  47. num: calc.num1
  48. })
  49. },
  50. //"="按钮事件处理函数
  51. execBtn: function(){
  52. //解决没有输入第2个数字,不能按=号问题
  53. if(this.numChangeFlag){
  54. this.numChangeFlag=false
  55. this.execflag=true
  56. calc.num2=this.data.num
  57. }
  58. //如果已经输入第2个数字,执行计算操作
  59. if(this.execflag){
  60. this.resultflag=true
  61. var result=calc.getResult()
  62. this.setData({
  63. sub: calc.num1+' '+calc.op+' '+calc.num2+'=',
  64. num: result
  65. })
  66. calc.num1=result
  67. }
  68. } ,
  69. //重置按钮事件处理函数
  70. resetBtn:function(){
  71. calc.reset()
  72. this.execflag=false
  73. this.numChangeFlag=false
  74. this.resultflag=false
  75. this.setData({
  76. sub: '',
  77. num: '0'
  78. })
  79. },
  80. //小数点按钮事件
  81. dotBtn:function(){
  82. //如果是计算结果状态,则重置计算器
  83. if(this.resultflag){
  84. this.resetBtn()
  85. }
  86. //如果等待输入第2个数字且还没有输入第2个数字,设为‘0’
  87. if(this.numChangeFlag) {
  88. this.numChangeFlag=false
  89. calc.setNum('0.')
  90. } else if(this.data.num.indexOf('.')<0){
  91. //如果当前数字没有".",需要加上"."
  92. calc.setNum(this.data.num+'.')
  93. }
  94. this.setData({
  95. num: calc.getNum(),
  96. })
  97. },
  98. //删除按钮事件处理函数
  99. delBtn:function(){
  100. //如果当前是计算结果状态,则重置计算器
  101. if(this.resultflag) {
  102. return this.resetBtn()
  103. }
  104. //非计算结果状态
  105. var num=this.data.num.substr(0,this.data.num.length-1)
  106. calc.setNum(num==='' || num==='-' || num==='-0.' ? '0' : num)
  107. this.setData({
  108. num: calc.getNum()
  109. })
  110. },
  111. //正负切换按钮事件处理函数
  112. negBtn:function(){
  113. //如果是0,不加正负号
  114. if(this.data.num==='0' || this.data.num==='0.'){
  115. return
  116. }
  117. //如果当前是计算结果状态,则重置计算器
  118. if(this.resultflag){
  119. this.resetBtn()
  120. } else if(this.data.num.indexOf('-')<0){
  121. //当前没有负号,加负号
  122. calc.setNum('-'+this.data.num)
  123. } else {
  124. //当前有负号,去掉负号
  125. calc.setNum(this.data.num.substr(1))
  126. }
  127. this.setData({
  128. num: calc.getNum()
  129. })
  130. },
  131. })

 模块首先使用require()函数引入计算模块,其次是全局变量、事件处理函数,具体事件处理函数如下:

numBtn:数字键处理函数,具体逻辑如下:首先判断是否是结果状态,如果是结果状态则复位,否则判断是第二操作数状态,是则设置为第二操作数。最后,使用计算模块的setNum设置操作数,并使用setData进行双向绑定的数据显示。

execBtn:"="事件处理函数,此函数的主要作用是调用计算模块的getResult函数,获取计算结果,并使用setData进行双向绑定的数据显示。

其它的事件处理函数如代码所示,分别完成复位、小数点、删除等处理函数,处理逻辑请参照代码。

本文主要论述了微信小程序计算器的设置,从思路、界面、计算模块、处理逻辑等方面进行了详细的论述,并给出了源代码。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/911392
推荐阅读
相关标签
  

闽ICP备14008679号