---
# System prepended metadata

title: Calculator 計算機攻略
tags: [JavaScript]

---

###### tags: `JavaScript`
# Calculator 計算機攻略

[程式碼 CodePen](https://codepen.io/enzoLuo/pen/jOrjBKP)


## 目標
1. 能做簡單四則運算
2. 可以使用鍵盤做操作
3. 數字位數過多處理
4. 功能按鍵

## UI
參考範本: IOS計算機
![](https://i.imgur.com/wK8NM13.png)

上半圖數字的 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;
    }
}
```
