制作一款好看的計算器

      網友投稿 582 2025-04-04

      微信小程序總是學習知識點也是很枯燥的,那么就做個小栗子來緩解一下學習的疲倦吧(更新累了)

      像我學習小程序視頻教程中也有說過做計算器,不過教程中的計算器太粗糙了,只能計算一下就結束了。 這可不行,男人要持久:dog:

      所以我有感而發,準備做一個完整度高一些的簡單計算器,計算器的基本功能就模仿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語句遍歷渲染出按鍵

      {{ item.name }}

      計算邏輯

      這是整個過程中最復雜最困難的部分

      一開始我并沒有添加記錄上一個按鍵的屬性,這導致了我一開始的判斷做的很累,而且還不完善

      然后又把邏輯給重新寫了一下

      在按鍵按下去的功能中,最重要的是計算和等于兩種

      計算中按鍵判斷大致相同,首先先準備一個計算方法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等對象

      {{ calNum1 }} {{ calIcon }} {{ calNum2 }} {{ calIconEQ }} {{ resultNum }}

      因為鍵盤按鍵是使用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

      {{ calNum1 }} {{ calIcon }} {{ calNum2 }} {{ calIconEQ }} {{ resultNum }} {{ item.name }}

      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: '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:正負 }, // 鍵盤點擊事件 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' ) { // 是否等于過 if (this.data.calIconEQ) { this.clearScreen(); } this.data.resultNum = ''; } this.data.resultNum += n.name; } this.setData({ resultNum: this.data.resultNum }) this.data.lastbtn = 0; //更新最新按下按鈕 } else if(n.type == 0){ // 判斷執行哪個方法 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; } } }, // 相加 add () { let data = this.data; if (data.lastbtn == 1 && data.calIcon == '+') return ; // 上一次數字 if (data.lastbtn == 0) { let res = this.compute(data.calNum1, data.resultNum, '+') this.setData({ calNum1: res }) this.setData({ resultNum: res }) } // 上一次等于 if (data.lastbtn == 2 && data.calIconEQ) { this.setData({ calNum1: data.resultNum }) this.setData({ calNum2: '' }) this.setData({ calIconEQ: '' }) } // 如果界面為空 if (!data.calNum1 && !data.calIcon) { this.setData({ calNum1: data.resultNum }); } this.setData({ calIcon: '+' }); data.lastbtn = 1; //更新最新按下按鈕 }, // 清除 clearScreen () { this.setData({ resultNum: '0' }); this.setData({ calNum1: '' }); this.setData({ calNum2: '' }); this.setData({ calIcon: '' }); this.setData({ calIconEQ: '' }); this.data.lastbtn = 3; //更新最新按下按鈕 console.clear() }, // 正負 isNegative (){ let data = this.data; data.resultNum = parseFloat(data.resultNum); //數值變字符串 if (data.resultNum > 0){ this.setData({ resultNum: -data.resultNum }) } else { this.setData({ resultNum: Math.abs(data.resultNum) }) } data.lastbtn = 4; //更新最新按下按鈕 }, // 余數 remainder () { let data = this.data; if (data.lastbtn == 1 && data.calIcon == '%') return ; // 上一次數字 if (data.lastbtn == 0) { if (!data.calNum1 && !data.calIcon) { this.setData({ calNum1: data.resultNum }) } else { let res = this.compute(data.calNum1, data.resultNum, '%') this.setData({ calNum1: res }) this.setData({ resultNum: res }) } } // 上一次等于 if (data.lastbtn == 2 && data.calIconEQ) { this.setData({ calNum1: data.resultNum }) this.setData({ calNum2: '' }) this.setData({ calIconEQ: '' }) } // 如果界面為空 if (!data.calNum1 && !data.calIcon) { this.setData({ calNum1: data.resultNum }); } this.setData({ calIcon: '%' }); data.lastbtn = 1; //更新最新按下按鈕 }, // 除法 division () { let data = this.data; if (data.lastbtn == 1 && data.calIcon == '÷') return ; if (data.calIconEQ) { } // 上一次數字 if (data.lastbtn == 0) { if (!data.calNum1 && !data.calIcon) { this.setData({ calNum1: data.resultNum }) } else { let res = this.compute(data.calNum1, data.resultNum, '÷') this.setData({ calNum1: res }) this.setData({ resultNum: res }) } } // 上一次等于 if (data.lastbtn == 2 && data.calIconEQ) { this.setData({ calNum1: data.resultNum }) this.setData({ calNum2: '' }) this.setData({ calIconEQ: '' }) } // 如果界面為空 if (!data.calNum1 && !data.calIcon) { this.setData({ calNum1: data.resultNum }); } this.setData({ calIcon: '÷' }); data.lastbtn = 1; //更新最新按下按鈕 }, // 乘法 multiplication () { let data = this.data; if (data.lastbtn == 1 && data.calIcon == '×') return ; // 上一次數字 if (data.lastbtn == 0) { let res = this.compute(data.calNum1, data.resultNum, '×') this.setData({ calNum1: res }) this.setData({ resultNum: res }) } // 上一次等于 if (data.lastbtn == 2 && data.calIconEQ) { this.setData({ calNum1: data.resultNum }) this.setData({ calNum2: '' }) this.setData({ calIconEQ: '' }) } // 如果界面為空 if (!data.calNum1 && !data.calIcon) { this.setData({ calNum1: data.resultNum }); } this.setData({ calIcon: '×' }); data.lastbtn = 1; //更新最新按下按鈕 }, // 減法 reduce() { let data = this.data; if (data.lastbtn == 1 && data.calIcon == '-') return ; // 上一次數字 if (data.lastbtn == 0) { if (!data.calNum1 && !data.calIcon) { this.setData({ calNum1: data.resultNum }) } else { let res = this.compute(data.calNum1, data.resultNum, '-') this.setData({ calNum1: res }) this.setData({ resultNum: res }) } } // 上一次等于 if (data.lastbtn == 2 && data.calIconEQ) { this.setData({ calNum1: data.resultNum }) this.setData({ calNum2: '' }) this.setData({ calIconEQ: '' }) } // 如果界面為空 if (!data.calNum1 && !data.calIcon) { this.setData({ calNum1: data.resultNum }); } this.setData({ calIcon: '-' }); data.lastbtn = 1; //更新最新按下按鈕 }, // 結果 equalRes() { let data = this.data; let res; // 判斷是否等于過 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 ; // 判斷有沒有后一個數 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; //更新最新按下按鈕 }, 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; } })

      javaScript web前端 小程序

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:WPS表格辦公—批量刪除數據后綴(wps表格批量添加后綴)
      下一篇:wps office怎么全屏
      相關文章
      亚洲另类无码专区首页| 亚洲人成网站在线观看播放青青| 亚洲一区二区三区在线观看蜜桃 | 亚洲熟女乱色一区二区三区| 亚洲综合综合在线| 亚洲在成人网在线看| 亚洲第一页中文字幕| 亚洲成人在线免费观看| 91嫩草亚洲精品| 亚洲理论在线观看| 亚洲欧洲高清有无| 亚洲va精品中文字幕| 中文字幕 亚洲 有码 在线| 亚洲人成www在线播放| 亚洲色大成网站www永久男同| 亚洲色在线无码国产精品不卡| 亚洲自偷自偷在线成人网站传媒| 亚洲午夜成人精品无码色欲| 亚洲一卡一卡二新区无人区| 亚洲啪AV永久无码精品放毛片| 亚洲成a人片在线观看天堂无码 | 久久亚洲一区二区| 亚洲视频2020| 亚洲国产综合人成综合网站00| 亚洲一级黄色大片| 亚洲熟妇AV乱码在线观看| 国产精品亚洲av色欲三区| 亚洲AV无码专区日韩| 国产亚洲视频在线播放| 亚洲av永久无码精品漫画| 久久亚洲精品无码AV红樱桃| 亚洲一级大黄大色毛片| 亚洲熟妇AV一区二区三区浪潮 | 成人亚洲国产精品久久| 亚洲国产人成中文幕一级二级| 国产乱辈通伦影片在线播放亚洲| 亚洲人成人无码网www电影首页| 亚洲av日韩av天堂影片精品| 亚洲第一永久在线观看| 亚洲综合精品伊人久久| 亚洲A∨午夜成人片精品网站 |