30개의 프로젝트로 배우는 프론트엔드 with VanillaJS (5) BMI 계산기

productuidev·2022년 9월 26일
0

FE Study

목록 보기
57/67
post-thumbnail

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

(5) BMI 계산기

1) UI 및 유저 흐름 설계

BMI 알아보기

디자인 가이드

Figma를 통해 간단 구현

2) Form과 User Flow

(1) 몸무게와 신장, 결과 버튼 만들기

index.html

  <form>
    <div class="row">
      <div class="form-input">
        <label for="bmi-weight">몸무게(kg)</label>
        <input id="bmi-weight" class="input" name="bmi-weight" type="number" value="" placeholder="kg 단위">
      </div>

      <div class="form-input">
        <label for="bmi-height">신장(cm)</label>
        <input id="bmi-height" class="input" name="bmi-height" type="number" value="" placeholder="cm 단위">
      </div>

      <div class="form-button">
        <button type="submit" id="resultBtn" class="btn-result">결과</button>
      </div>
    </div>
  </form>

main.css

form {width:100%;}
.row {display:flex;flex-direction:row;justify-content:center;gap:4px;margin-bottom:4px;}
.form-input {display:flex;flex-direction: column;margin-left:4px;}
.form-input label {color:#6B778C;font-size:12px;line-height:16px;margin-bottom:4px;font-weight:800;}
.form-input input {background-color:#FAFBFC;border:2px solid #DFE1E6;margin:0;padding:0 12px;width:200px;height:48px;box-sizing: border-box;outline: none;border-radius:4px;color:#091E42;}
.form-input input::placeholder {color:#a5aec4;}
.form-button {margin:20px 0 0 4px;}
.btn-result {padding:0 40px;height:48px;background-color:#0E1E3A;color:#FFF;text-align: center;border-radius:4px;display:flex;justify-content:center;align-items:center;border:none;}
.btn-result.line {color:#0E1E3A;border:1px solid #0E1E3A;background-color:#FFF;margin-top:8px;}

(2) BMI 수치와 상태 표시 결과, 초기화 버튼 만들기

  • 저체중 underweight, 정상 normal, 과체중 overweight, 비만 obesity
  • progress : min(최소값), max(최대값), optimum(적정값), low, high 지정 (상단의 체질량지수 값 참조)

index.html

<form>

...

    <div id="res">
      <div class="bmi-wrap">
        <progress id="bmi-progress" class="progress" value="" min="0" max="100" optimum="23" low="18.5" high="25"></progress>
        <div class="bmi-message">
          <p class="main">당신의 BMI는 <strong id="bmi" class="msg-color"></strong> 입니다.</p>
          <p class="sub"><strong id="state" class="msg-color"></strong> 입니다.</p>
        </div>
        <div class="row">
          <button type="reset" id="reset" class="btn-result line" style="display:none;">초기화</button>
        </div>
      </div>
    </div>
</form>

main.css

.bmi-wrap {display:flex;flex-direction: column;align-content: center;margin:36px 0;}
.progress {appearance: none; width:512px; height:6px; margin:0 auto;}
.progress::-webkit-progress-bar {background:#EBECF0;border-radius:6px;box-shadow: inset 3px 3px 10px #EBECF0;}
.progress::-webkit-progress-value {border-radius:6px;}
.progress.normal::-webkit-progress-value {background: #11A65E;}
.progress.underweight::-webkit-progress-value,
.progress.overweight::-webkit-progress-value,
.progress.obesity::-webkit-progress-value {background: #E31C1C;}
.bmi-message {margin:24px 0 12px;text-align:center;}
.bmi-message .main {height:30px;font-size:18px;line-height:24px;margin-bottom:8px;}
.bmi-message .sub {height:30px;font-size:14px;line-height:20px;}
.bmi-message .msg-color {display:inline-block;font-weight:800;width:80px; border-bottom:1px solid #0E1E3A;}

3) BMI 로직 구현하기

Point : 체중(kg)를 신장(cm)의 제곱으로 나눈 값

(1) 구현 로직 정리

  • 몸무게와 신장을 입력 후 결과 버튼을 눌렀을 때 하단 res(결과) 표시
  • 초기화 버튼 누르면 form 초기화 (결과에 걸린 입력값, 진행률, 결과값 상태 모두 초기화 시키기)
  • 입력한 값이 적절한 값이 아닐 경우 alert 메시지 띄우기
  • BMI 계산 : 소수점 2자리 까지 표시
  • BMI 지수 구간 조건 4가지(저체중, 정상체중, 과체중, 비만)에 대한 진행률, 결과값 표시

main.js

function onSubmit(event) {
  event.preventDefault();

  // 입력란의 문자열을 실수로 변경
  const w = parseFloat(event.target[0].value)
  const h = parseFloat(event.target[1].value)

  console.log(w, h)

  // 조건 : 숫자인지, 양수인지
  // parseFloat : 수가 아닌 문자로 시작하면 NaN을 반환하므로 isNaN 함수 사용 (isNaN : 숫자가 아닌 값을 찾음)
  if(isNaN(w) || isNaN(h) || w <= 0 || h <= 0) {
    alert("적절한 값이 아닙니다.")
    return;
  }

  // BMI 계산 : 소수점 2자리까지 표시(toFixed)
  const bmi = w / ((h/100) * (h/100))
  console.log(bmi.toFixed(2))

  // submit 시 결과 표시
  const res = document.getElementById("res")
  res.style.display = "block"

  // submit 시 초기화 버튼 표시
  const resetBtnEl = document.getElementById("reset")
  resetBtnEl.style.display = "block"

  // BMI 수식 및 진행률 표시
  const bmiEl = document.getElementById("bmi");
  const progressEl = document.getElementById("bmi-progress");
  bmiEl.innerText = bmi.toFixed(2)
  progressEl.value = bmi

  let state;
  let common = true

  if(bmi < 18.5) {
    state = "저체중"
    common = false;
    progressEl.classList.add('underweight')
  }
  if(bmi >= 18.5 && bmi <= 23) {
    state = "정상체중"
    common = true;
    progressEl.classList.add('normal')
  }
  if(bmi >= 23 && bmi <= 25) {
    state = "과체중"
    common = false;
    progressEl.classList.add('overweight')
  }
  if(bmi >= 25) {
    state = "비만"
    common = false;
    progressEl.classList.add('obesity')
  }

  const stateEl = document.getElementById("state");
  stateEl.innerText = state
  stateEl.style.color = common ? "#11A65E" : "#E31C1C"
  bmiEl.style.color = common ? "#11A65E" : "#E31C1C"

  // 초기화버튼 시 진행률 초기화
  const resutBtnEl = document.getElementById("resultBtn");
  resetBtnEl.addEventListener("click", function() {
    progressEl.classList.remove('underweight');
    progressEl.classList.remove('normal');
    progressEl.classList.remove('overweight');
    progressEl.classList.remove('obesity');
  });
}

(2) onsubmit 시 onSubmit 함수 실행, onreset 시 res 결과 숨김(초기화)

index.html

<form onsubmit="onSubmit(event)" onreset="document.getElementById('res').style.display = 'none'">
	
    ...
    ...
    
</form>

결과


💬 간만에 1개로 정리한 강의, 이번 강의는 어렵지 않아서 원래 있던 내용에 몇 가지 사항을 응용해보았다. 찾아보면 같은 BMI 구현인데 다양한 방식이 있는 거 같았다.

  • BMI 계산식 (console.log에서 00.0000으로 나와서 다른 수식으로...)
  • BMI 수식 조건 추가 (체질량지수 기준 참고)
  • 강의에선 진행률이 meter tag로 쓰였는데, 표시 에러가 나서 progress로 변경
  • 각 상태에 따른 progress bar 표시 조건 + 초기화 추가

다른 예제 코드

💬 건강 TMI
이전 직장에서 집이 가까운 거리(25분) + 개발공부시작 + 스트레스 폭식 + 먹고 바로 눕기 등등을 하면서 현재 회사 입사 당시 4kg가 찐 상태였다. 아침 일찍+야근 등 바이오리듬도 불안정한 것 같아 체중감량과 절식, 심신안정에 도움이 되는 한약을 지어먹고 있다. 나이가 들수록 내적으로 여러 질환이 올 수 있기 때문에 적절하게 관리하는 것이 중요한 것 같다. 특히 컴퓨터를 많이 보는 직업군이라면 더더욱.. 그 외에도 영양제 12종을 챙겨 먹고 있는데.. 4년 전 우연히 본 이 블로그를 계기로.. (약쟁이?) 열심히 일하려면 아무래도 건강 관리가 무엇보다 중요한 것 같다. (요즘은 바쁜 와중인데 어느 정도 적응이 되고, 업무가 안정화 되면 운동도 병행할 예정이다 💪..) 그치만 식습관이 제일 중요..(군것질...)

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

0개의 댓글