###### tags: `JavaScript`
# Calculator 計算機攻略
[程式碼 CodePen](https://codepen.io/enzoLuo/pen/jOrjBKP)
## 目標
1. 能做簡單四則運算
2. 可以使用鍵盤做操作
3. 數字位數過多處理
4. 功能按鍵
## UI
參考範本: IOS計算機

上半圖數字的 info 區塊, 下半部按鍵的 keypad 區塊
keypad 區塊分兩種按鍵 數字按鍵及功能按鍵
* 資訊顯示
1. 數值顯示 ()
2. operator (x, +, - ...etc)
3. status (overflow, full)
* 功能按鍵
1. +, -, x, ÷, =
2. C, +-, %, .
* 數字按鍵
1. Number 0~9
## 設計想法
將計算機用物件包裝起來
```javascript=
const calculator = {
value: 0, // 儲存目前的值(基本上與計算機中的值一樣)
operator: '', // 存放運算子, 點選加減乘除會放進來並更新畫面右上角, 提醒目前的運算)
valueTemp: 0, // 使用運算子後會把原本的 value存放過來, 用來計算用, 使用'='後清空
isFullSize: false, // 數字位數是否過多? 為true時無法輸入並顯示在左上角資訊
isOverFlow: false, // 是否溢位, 如果計算結果為 e+ 科學記號時觸發, 並無法再計算
renderValue(value) {}, // 渲染畫面 value 位置的 function
renderOperator(operator) {}, // 渲染畫面 operator資訊的 function
checkInfoSize(len) {}, // 檢查目前畫面是否滿了, 並更新 isFullSize 值
renderBool() {}, // 將目前 isFullSize 及 isOverFlow 渲染到畫面上
funcNumKey(keyValue) {}, // 使用數字按鍵觸發的 function
funcOperatorKey(keyValue) {}, // 使用功能按鍵觸發的 function
}
```
## 功能需求
### 數字按鍵
1. 1~9 可以直接對value相加, 要注意的是要字串相加並非數字相加
2. 為0的時候, 輸入0應該使其無法輸入直接 reject
### 基本運算(加減乘除)
原本的做法如下, 後來看到有人利用 eval()函式並試著使用, eval可以自動把字串轉換並返回計算結果
```javascript=
function count() {
switch (opTemp) {
case '+':
infoEl.textContent = numTemp + Number(infoEl.textContent);
break;
case '-':
infoEl.textContent = numTemp - Number(infoEl.textContent);
break;
case 'x':
infoEl.textContent = numTemp * Number(infoEl.textContent);
break;
case '÷':
infoEl.textContent = (numTemp / Number(infoEl.textContent)).toFixed(2);
break;
}
}
```
使用 eval();
```javascript=
let result = String(eval(`${this.valueTemp}${operator}${this.value}`));
```
### 特殊功能
1. AC 功能
* 清除所有的value, operator, 暫存, 所有狀態 並恢復成0
2. +- 功能
* 如果 value 為 0 不具效果
3. % 功能
* 每次除 100 並返回, 如果最後 0.00 使其下一動為 0
4. 小數點('.') 功能
* 如果已經有小數點不具作用
### 數字位數過多時處理
利用字串長度判斷數字位數是否過多, 並依照目前的數字位數給予不同的字體大小, 最後超過令使用者無法輸入
```javascript=
checkInfoSize(len) {
let valueLen = String(this.value).length;
if(valueLen < 7) {
infoValue.style['font-size'] = '80px';
this.isFullSize = false;
} else if (valueLen < 9) {
infoValue.style['font-size'] = '65px';
this.isFullSize = false;
} else if (valueLen < 11) {
infoValue.style['font-size'] = '50px';
this.isFullSize = false;
} else if (valueLen < 14) {
infoValue.style['font-size'] = '36px';
this.isFullSize = false;
} else if (valueLen < 19) {
infoValue.style['font-size'] = '30px';
this.isFullSize = false;
} else {
this.isFullSize = true;
}
}
```