30개의 프로젝트로 배우는 프론트엔드 with VanillaJS (4-2) 버튼 기반 계산기

productuidev·2022년 9월 20일
0

FE Study

목록 보기
56/67
post-thumbnail

[fastcampus] 30개의 프로젝트로 배우는 프론트엔드 with VanillaJS (4-2)

(4) 버튼 기반 계산기 구현하기

3) UI 구현 (HTML, CSS)

  • 이전 시간에 만든 간단한 디자인 가이드를 통해 계산기 UI 구현
  • 상단 input : 숫자와 연산이 나오는 form (버튼 기반이므로 버튼에서 누른 내용을 보여주는 form)
  • row행 : 숫자와 연산 버튼, flex 활용

index.html

  <!-- 버튼 기반 계산기 -->
  <div class="row">
    <input id="top-input" class="input" type="text" value="" disabled>
  </div>
  <div class="row">
    <button class="btn">7</button>
    <button class="btn">8</button>
    <button class="btn">9</button>
    <button class="btn">=</button>
  </div>
  <div class="row">
    <button class="btn">4</button>
    <button class="btn">5</button>
    <button class="btn">6</button>
    <button class="btn">+</button>
  </div>
  <div class="row">
    <button class="btn">1</button>
    <button class="btn">2</button>
    <button class="btn">3</button>
    <button class="btn">-</button>
  </div>
  <div class="row">
    <button class="btn btn-lg">0</button>
    <button class="btn">/</button>
    <button class="btn">*</button>
  </div>

main.css

.row {display:flex;flex-direction:row;gap:4px;margin-bottom:4px;}
.btn {width:48px;height:48px;background-color:#2699FB;color:#FFF;border-radius:4px;display:flex;justify-content:center;align-items:center;border:none;font-size:12px;font-weight:700;}
.btn:active {background-color:#007FEB;}
.btn-lg {width:100px;height:48px;}
.input {margin:0;margin-bottom:4px;padding:0 12px;width:204px;height:48px;box-sizing:border-box;outline:none;}
.input:disabled {background-color:#FFF;border:1px solid #BCE0FD;color:#BCE0FD;font-size:14px;}

CSS의 gap 속성 활용

grid, flex 및 column 레이아웃 내의 행과 열 사이의 공간인 여백의 크기를 지정

4) 계산기 로직 구현 : 숫자 입력

버튼을 통해 숫자, 연산기호 등을 통해 입력하여 실제 결과가 나오도록 로직 구현

index.html

  <!-- 버튼 입력 시 input에 숫자, 연산 등이 입력되어 계산기 기능 구현 -->
  <div class="row">
    <input id="top-input" class="input" type="text" value="" disabled>
  </div>
  • 연산자를 기준으로 left(왼쪽에 입력되는 숫자값), right(오른쪽에 입력되는 숫자값), oper(operator, 연산자)
  • 이미 알고 있어서 null을 명시적으로 넣어줌 (명시적으로 값이 비어있음을 나타내는데 사용, 비어있는 값(아무런 값이 아닌 값 = no value)
  • 일치 연산자 (===) : 자료형 변환 없이 두 피연산자가 엄격히 같은지 판별

main.js

let left = null,
    right = null,
    oper = null;

function inputNum(num) {
    if (oper === null) {
        if (left === null) {
            left = `${num}`
        }
        else {
            left += `${num}`
        }
    }
    else {
        if (right === null) {
            right = `${num}`
        }
        else {
            right += `${num}`
        }
    }
}
  • ${num} : formatting (or num.toString())
  • 연산자가 입력되면 왼쪽에는 숫자를 표시하거나 아니면 숫자를 더해줌
  • 연산자가 입력되지 않았다면 오른쪽에는 숫자를 표시하거나 아니면 숫자를 더해줌

index.html

각각의 btn div에 onclick 이벤트 넣어주기

  <div class="row">
    <input id="top-input" class="input" type="text" value="" disabled>
  </div>
  <div class="row">
    <button class="btn" onclick="inputNum(7)">7</button>
    <button class="btn" onclick="inputNum(8)">8</button>
    <button class="btn" onclick="inputNum(9)">9</button>
    <button class="btn">=</button>
  </div>
  <div class="row">
    <button class="btn" onclick="inputNum(4)">4</button>
    <button class="btn" onclick="inputNum(5)">5</button>
    <button class="btn" onclick="inputNum(6)">6</button>
    <button class="btn">+</button>
  </div>
  <div class="row">
    <button class="btn" onclick="inputNum(1)">1</button>
    <button class="btn" onclick="inputNum(2)">2</button>
    <button class="btn" onclick="inputNum(3)">3</button>
    <button class="btn">-</button>
  </div>
  <div class="row">
    <button class="btn btn-lg" onclick="inputNum(0)">0</button>
    <button class="btn">/</button>
    <button class="btn">*</button>
  </div>
  • 0부터 시작하는 값은 계산기에서 00000.. 이런 식으로 여러 번 입력될 수 없으므로 해당 조건 추가
  • 숫자가 0이고 입력값도 0이면 return

main.js

function inputNum(num) {
    if (oper === null) {
        if (left === null) {
            left = `${num}`
        }
        else {
        	// !
            if (num === 0 && parseInt(left) === 0)
                return;
                
            left += `${num}`
        }
    }
    else {
        if (right === null) {
            right = `${num}`
        }
        else {
        	// !
            if (num === 0 && parseInt(right) === 0)
                return;
            right += `${num}`
        }
    }
}
  • =을 눌렀는지 여부를 판별하기 위해 res 추가 (처음에 안 눌렀으므로 false가 default)
  • left, right가 존재 시 input에 적용하는 함수 save 생성
  • save 호출하여 바로 input에서 대응되도록 적용

main.js

let left = null,
    right = null,
    oper = null,
    res = false;
    
function save() {
    const inp = document.getElementById("top-input");
    let value = "" // 값(상수)

    if (left === null)
        return;
    value += left + " "
    inp.value = value // 결과값

    if (oper === null)
        return;
    value += oper + " "
    inp.value = value // 결과값

    if (right === null)
        return;
    value += right + " "
    inp.value = value // 결과값

	// 참이면
    if (res) { 
        let res = "";
        
        // 사칙연산
        switch (oper) { 
            case "+":
                res = parseInt(left) + parseInt(right)
                break;
            case "-":
                res = parseInt(left) - parseInt(right)
                break;
            case "*":
                res = parseInt(left) * parseInt(right)
                break;
            case "/":
                res = parseInt(left) / parseInt(right)
                break;
        }

        value += `= ` + res;
        inp.value = value // 결과값
    }
}

function inputNum(num) {

	...
    ...
 
 	save(); 
}
  • console을 통해 체크

5) 계산기 로직 구현 : 연산자 입력1

  • 연산하는 함수 추가 후 버튼에 onclick 추가

index.html

  <div class="row">
    <input id="top-input" class="input" type="text" value="" disabled>
  </div>
  <div class="row">
    <button class="btn" onclick="inputNum(7)">7</button>
    <button class="btn" onclick="inputNum(8)">8</button>
    <button class="btn" onclick="inputNum(9)">9</button>
    <button class="btn">=</button>
  </div>
  <div class="row">
    <button class="btn" onclick="inputNum(4)">4</button>
    <button class="btn" onclick="inputNum(5)">5</button>
    <button class="btn" onclick="inputNum(6)">6</button>
    <button class="btn" onclick="inputOper('+')">+</button> <!-- 더하기 -->
  </div>
  <div class="row">
    <button class="btn" onclick="inputNum(1)">1</button>
    <button class="btn" onclick="inputNum(2)">2</button>
    <button class="btn" onclick="inputNum(3)">3</button>
    <button class="btn" onclick="inputOper('-')">-</button> <!-- 빼기 -->
  </div>
  <div class="row">
    <button class="btn btn-lg" onclick="inputNum(0)">0</button>
    <button class="btn" onclick="inputOper('/')">/</button> <!-- 나누기 -->
    <button class="btn" onclick="inputOper('*')">*</button> <!-- 곱하기 -->
  </div>
  • 연산자의 경우, null일 때는 input이 안되어야 함
  • 음수일 경우 (parseInt 시 음수로 표시)
  • left가 null은 아닌데 마이너스일 경우
  • null이 아니면 연산자에 담아준다
  • input에 입력되도록 save 각각 호출 (음수일 때 나오게, 왼쪽 오른쪽이 연산되게)

main.js


function inputOper(op) {
    if(left === null && op === "-") {
        left = "-"
        save();
        return;
    } 
    if(left === "-" && op === "-") {
        return;
    } 
    oper = op;
    save();
}

  • 일반적인 계산기 로직과 다르게 operator가 입력된 상태에서도 오른쪽을 음수로 바꿀 수 있게 로직 추가
  • 연산자가 마이너스인데 기존의 값이 존재하고(null이 아닐 때) right가 null이면

main.js

function inputOper(op) {
    if(left === null && op === "-") {
        left = "-"
        save();
        return;
    }
    if(left === "-" && op === "-") {
        return;
    }
    if(op === "-" && op !== null && right === null) {
        right = "-"
        save();
        return;
    }
    oper = op;
    save();
}

6) 계산기 로직 구현 : 연산자 입력2

  • =(equal)으로 연산 결과가 나오도록 로직 구현 (inputEqu 함수)
  • res는 =을 눌렀는지 안 눌렀는지의 여부 (눌렀기 때문에 true), 누른 후 save 호출
  • res를 도출하기 위해 사칙연산 부분의 res를 전역변수로 변경 (resValue는 최종 계산값)

main.js

let left = null,
    right = null,
    oper = null,
    res = false,
    resValue = null;

function save() {
	...

    if (res) {
        // let resValue = "";
        switch (oper) {
            case "+":
                resValue = parseInt(left) + parseInt(right)
                break;
            case "-":
                resValue = parseInt(left) - parseInt(right)
                break;
            case "*":
                resValue = parseInt(left) * parseInt(right)
                break;
            case "/":
                resValue = parseInt(left) / parseInt(right)
                break;
        }

        value += `= ` + resValue;
        inp.value = value
    }
}
  • = 버튼에 onlick 적용

index.html

    <button class="btn" onclick="inputEqu()">=</button>
  • =을 누르면 결과값 계산
  • 계산된 상태에서 =을 한번 더 누르면 계산식과 연산자는 모두 초기화 후 최종 계산값인 resValue만 보여줌

main.js

function inputEqu() {
    if(res) {
        left = resValue
        right = null
        resValue = null
        oper = null
        res = false
    }
    else {
        res = true
    }
    save();
}


로직부분은 어려워서 2번 봄..

profile
필요한 내용을 공부하고 저장합니다.

0개의 댓글