動手做一個酷炫(並不)的計算器(一)

飛天麵條發表於2018-04-10

本文為學習 How to build a calculator—part 1的記錄。建議看原文!

動手做一個酷炫(並不)的計算器(一)
拋去廢話,直接開擼

先搭個頁面結構

看上圖,這個計算器分兩個主要部分:螢幕、鍵盤:

<div class="calculator">
  <div class="calculator__display">0</div>
  <div class="calculator__keys">
  </div>
</div>
複製程式碼

鍵盤部分有+-*/等按鍵:

    <div class="calculator__keys">
        <button class="keys--operator" data-action="add">+</button>
        <button class="keys--operator" data-action="sub">-</button>
        <button class="keys--operator" data-action="multi">*</button>
        <button class="keys--operator" data-action="div">/</button>
        <button>7</button>
        <button>8</button>
        <button>9</button>
        <button>4</button>
        <button>5</button>
        <button>6</button>
        <button>1</button>
        <button>2</button>
        <button>3</button>
        <button>0</button>
        <button data-action="decimal">.</button>
        <button data-action="clear">AC</button>
        <button class="key--equal" data-action="calculate">=</button>
    </div>
複製程式碼

整個頁面就這麼多東西了~

再加點樣式

計算器放在整個網頁的中間好看點

body{
    height: 100vh;
    background-image: linear-gradient(236deg, #74ebd5, #acb6e5);
    display: flex;
    justify-content: center;
    align-items: center;
}
複製程式碼

再來個圓角,美觀

.calculator {
    border-radius: 12px;
    box-shadow: 0 0 40px 0 rgba(0, 0, 0, 0.15);
    overflow: hidden;
}
複製程式碼

顯示器的背景偏黑色,數字是白色的。

.calculator__display {
    background-color: #222;
    color: #fff;
    font-size: 2em;
    padding: 0.5em 0.75em;
    text-align: right;
}
複製程式碼

按鍵用 grid 佈局,輕鬆搞定

.calculator__keys {
    background-color: #999;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-gap: 1px;
}
.calculator__keys>* {
    background-color: #fff;
    padding: 0.5em 1.25em;
    position: relative;
    text-align: center;
}
.keys--operator {
    background-color: #eee;
}
.key--equal {
    background-image: linear-gradient(to bottom, #fe886a, #ff7033);
    grid-column: -2;
    grid-row: 2/span 4;
}
複製程式碼

按鍵在點選的時候應該有按鍵效果,運算鍵被按下後也需要有提示

.calculator__keys>*:active::before,
.calculator__keys>.is-depressed::before {
    content: "";
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    background-color: rgba(0, 0, 0, 0.2);
    box-shadow: 0 0 3px 0 rgba(0, 0, 0, 0.5) inset;
    position: absolute;
}
複製程式碼

整個頁面就算完成了

開始處理運算邏輯

既然是計算器,肯定要監聽點選事件並且判斷點選的是哪一個按鍵。

const calculator = document.querySelector('.calculator');
const display = calculator.querySelector('.calculator__display');
const keys = calculator.querySelector('.calculator__keys');
keys.addEventListener('click',e=>{
    if(e.target.matches('button')){
        const key = e.target;
        const action = key.dataset.action;
        ...
    }
})
複製程式碼

按鍵從功能上分五種:數字鍵、運算鍵、小數點、清除鍵、求值鍵。其中運算鍵、小數點、清除鍵、求值鍵都有data-action屬性。沒有data-action屬性的就是數字鍵了。通過這個屬性判斷被點選的是哪種按鍵。

const action = key.dataset.action;
if(!action){
    console.log('number');
}else if(action === 'add' || action === 'sub' || action === 'multi' || action === 'div'){
    console.log('operator');
}else if(action === 'decimal'){
    console.log('decimal');
}else if(action === 'clear'){
    console.log('clear');
}else if(action==='calculate'){
    console.log('calculate');
}
複製程式碼

一般情況

點選數字鍵:

點選數字鍵分兩種情況:

  • 顯示器顯示為'0'時按數字鍵,顯示器上顯示的數字應該變成所按的數字
  • 顯示器不為'0'時按數字鍵,顯示器上顯示的數字應該是已顯示的數字最後一位加上所按的數字
if(!action){
  if(display.textContent ==='0'){
    display.textContent = key.textContent;  
  }else {
    display.textContent+=key.textContent;    
  }
}
複製程式碼

點選運算鍵

點選運算鍵後,應該有該鍵被按下的狀態提示

動手做一個酷炫(並不)的計算器(一)

if(action === 'add' || action === 'sub' || action === 'multi' || action === 'div'){
    key.classList.add('is-depressed');
}
複製程式碼

之後再點選其餘按鍵,被按下狀態提示應該取消

 const action = key.dataset.action;
 Array.from(key.parentNode.children).forEach(k => k.classList.remove('is-depressed')); 
複製程式碼

點選小數點

點選小數點後,小數點應該加在顯示器顯示的數字後面

if(action==='decimal'){
    display.textContent +='.';
}
複製程式碼

但是,假如顯示器上已經有小數點了,不應該響應這次點選,所以修改下程式碼

if(action==='decimal'){
    if(!display.textContext.includes('.')){
        display.textContext+='.'
    }
}
複製程式碼

點選清除鍵

AC 鍵是將計算器所有狀態重置。後面會加 CE 鍵。暫時就是重置顯示器:

if(action==='clear'){
    display.textContent='0';
}
複製程式碼

點選計算鍵

計算鍵簡單,就是算下加減乘除。寫個函式好了:

function calculate(firstValue,operator,secondValue){
    switch(operator){
        case 'add':
            return firstValue+secondValue;
        case "sub":
            return firstValue-secondValue;
        case "multi":
            return firstValue*secondValue;
        case "div":
            return firstValue/secondValue;
        default:
            return "NaN";
    }
}
if(action==='calculate'){
    display.textContent = calculate(firstValue,operator,secondValue);
}
複製程式碼

但是,firstValue,operator,secondValue從何而來?

secondValue就是當前螢幕上的內容,

secondValue =  display.textContent;
複製程式碼

firstValueoperator在點選計算鍵時還存在,趁機將其儲存起來

if(action === 'add' || action === 'sub' || action === 'multi' || action === 'div'){
    key.classList.add('is-depressed');
    calculator.dataset.operator = action;
    calculator.dataset.firstValue = display.textContent;
}
複製程式碼

修改一下點選計算鍵的程式碼:

const firstValue = calculator.dataset.firstValue;
const operator = calculator.dataset.operator;
const secondValue = display.textContent;
display.textContent = calculate(firstValue,operator,secondValue);
複製程式碼

新增清除按鈕的重置:

display.textContent='0';
calculator.dataset.firstValue ='';
calculator.dataset.operator = '';
複製程式碼

至此,一個未處理特殊情況,但功能還算完備的計算器就完成了。剩下的工作就是處理各種組合輸入,儘量讓計算器沒有 BUG。

相關文章