iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 15
0
自我挑戰組

花三十天找到 JavaScript 沙漠中的綠洲系列 第 15

15 來寫 BMI 計算機 (上)

前言

不知不覺也過了這趟旅途的一半,現在的你雖然邊走邊撿裝備,但也許對這些裝備能發揮什麼功效還不太了解。為了讓你知道現在的自己有多厲害,今明兩天,我們要一起來寫 BMI 計算機!跟著我一步一步運用前面 13 天學到的技能吧!

Let's go!

第一關:If 判斷式

先不用把 BMI 計算機想的太難,也先不用製作使用者輸入的地方。只要先讓計算機在算出 BMI 是過重時,網頁就顯示過重,過輕時就顯示過輕,那會用到的當然就是 If 判斷式囉!

計算與判斷方式如下: BMI = 體重(公斤) / 身高的平方(單位為公尺)

體重過輕:BMI < 18.5
正常:18.5≦BMI<24
過重:24≦BMI<27
輕度肥胖:27≦BMI<30
中度肥胖:30≦BMI<35
重度肥胖:BMI≧35

讓我們一起用判斷式寫寫看!建議可以先自己試著寫看看,再往下看,會比較知道哪邊不熟喔!

function calculationBMI(height,kg){
  let bmi = kg/(height/100*height/100)
  if(bmi<18.5){
    return "體重過輕"
  }else if(bmi>=18.5 && bmi<24){
    return "正常"
  }else if(bmi>=24 && bmi<27){
    return "過重"
  }else if(bmi>=27 && bmi<30){
    return "輕度肥胖"
  }else if(bmi>=30 && bmi<35){
    return "中度肥胖"
  }else{
    return "重度肥胖"
  }
}

首先要設定函式的參數為身高與體重,並宣告 bmi 的計算方式給電腦。再來很簡單,只要設定好如何判斷即可。這裡判斷的條件有運用到 && 這個邏輯運算子,因為是同時介於這兩種條件中,代表需要同時符合。一邊寫也可以一邊使用 console.log() 來確認,自己寫的是否正確。

第二關:.innerHTML 搭配 forEach 渲染到畫面上

剛剛我們寫好的判斷式,並不會出現在網頁上,只能從 console 面板看到。現在第二步,就是讓使用者能夠看到我們精美的作品。因為之後也是需要讓使用者輸入資料,請電腦計算後再做判斷,才將結果再次顯示於網頁中,因此是沒有辦法一開始就將內容寫到 html 裡的。這時候就可以用 innerHTML 啦!

為了讓事情不要一下子變得太過複雜,先讓我們用陣列的方式假裝使用者已經輸入過資料了,現在只要先把資料渲染到畫面上就好。要讓陣列依序做某件事情,則會運用到 forEach。

題目如下,請告訴我該怎麼完成這個程式!

  • html
<ul class="list"></ul>
  • css
.list-card{
  background: blue;
  width: 300px;
  margin: 0 auto;
  color: #fff;
  text-align: center;
  padding: 10px;
  margin-bottom: 30px;
}
  • js
let list = document.querySelector(".list")
let data = []; //宣告data是空的陣列
data.push( //依序把東西推進去
  {
    "name":"廖洧杰",
    "height":178,
    "weight":60,
    "bmi":18.9,
    "status":"正常"
  }
)
data.push(
  {
    "name":"小乖",
    "height":120,
    "weight":60,
    "bmi":41.6,
    "status":"重度肥胖"
  }
)
data.push(
  {
    "name":"小麗",
    "height":140,
    "weight":60,
    "bmi":30.6,
    "status":"中度肥胖"
  }
)
data.push(
  {
    "name":"小新",
    "height":80,
    "weight":60,
    "bmi":15.6,
    "status":"體重過輕"
  }
)
data.push(
  {
    "name":"小華",
    "height":50,
    "weight":60,
    "bmi":24,
    "status":"過重"
  }
)

寫完了嗎?要公布答案囉!

在 js 的部分,請接下去這樣寫:

let str = "";

data.forEach(function(item){
  let content = `<li class = "list-card">
                <h2>${item.name}</h2>
                <p>你的身高是${item.height}</p>
                <p>你的體重是${item.weight}</p>
                <p>你的 bmi 是${item.bmi}</p>
                <p>你的狀態是${item.status}</p>
                </li>`;
  str += content;
})

list.innerHTML = str;

這裡善用樣板字串,不但可以避免因為單引號和雙引號交雜產生的 bug ,也可以讓畫面更簡潔容易閱讀與維護唷!

第三關:

今天的練習快要結束了,最後要奉上 BMI 計算機的雛型給你,但當然不是白吃的午餐囉!請邊看邊想想,arrayBMIrecord 的陣列用途是什麼?calculateBMI 函式做了什麼? render 函式又做了什麼?

  • html
<input type="number" class="height" placeholder="請輸入您的身高(公分)">
<input type="number" class="kg" placeholder="請輸入您的體重(公斤)">
<input type="button" class="send" value="計算">

<h4>BMI 紀錄</h4>
<ul class="list"></ul>
  • css
.text-primary {
  color: green;
}
.text-secondary {
  color: blue;
}
.text-warning {
  color: orange;
}
.text-danger {
  color: red;
}
  • js
// 重新命名: 元素名稱+客製化名稱

const inputHeight  = document.querySelector('.height');
const inputKg      = document.querySelector('.kg');
const btnSend      = document.querySelector('.send');
const listRecord   = document.querySelector('.list');
const arrayBMIrecord = [];

/* 定義物件資料,此為 BMIData物件之所有屬性 */
const BMIData = {
  "overThin":{
    class:"text-secondary",
    nameStatus:"體重過輕"
  },
  "normal":{
    class:"text-primary",
    nameStatus: "正常"
  },
  "warning":{
    class:"text-warning",
    nameStatus: "過重"
  },
  "danger":{
    class:"text-danger",
    nameStatus: "危險"
  }
}

/* 渲染畫面 */
// forEach(),取出陣列所有物件並做處理

function render(){
  let str ='';
  arrayBMIrecord.forEach( function(item){
    return  str += '<li>BMI指數為 :'+ item.BMI + 
                     ' 狀態是 <span class="'+ 
                     BMIData[item.status].class+'">' + 
                     BMIData[item.status].nameStatus +'</span></li>'; 
  })
  listRecord.innerHTML = str;
}

/* 處理/加入資料, */
function calculateBMI(){
  const numberHeight = inputHeight.value;
  const numberKG = inputKg.value;
  const numberBMI = parseInt( numberKG / (( numberHeight/100 )**2 ));
  // 定義紀錄資料 
  const userRecord = {
    
    height:'',
    weight:'',
    BMI:'',
    status:'',
  }
  // 增加資料到物件
  userRecord.height = Number(numberHeight);
  userRecord.weight = Number(numberKG);
  userRecord.BMI    = numberBMI;
  if(numberBMI<18.5){
    userRecord.status='overThin'
  }else if(numberBMI>=18.5 && numberBMI<=23){
    userRecord.status='normal';
  }else if(numberBMI>23 && numberBMI<=35){
    userRecord.status='warning';
  }else{
    userRecord.status='danger';
  }
  // 增加物件到陣列
  arrayBMIrecord.push(userRecord);
  
  //渲染畫面
  render();

  inputHeight.value = '';
  inputKg.value = ``;
}

btnSend.addEventListener('click', calculateBMI);

那麼我們就明天見囉!晚安~

學習與參考資料

JS 學徒特訓班教學影片及練習題 13+18-19 關


上一篇
14 ES6:樣板字串與箭頭函式
下一篇
16 來寫 BMI 計算機 (下)
系列文
花三十天找到 JavaScript 沙漠中的綠洲35
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
看不清
iT邦新手 5 級 ‧ 2020-09-15 21:08:56

加油 加油 自我挑戰已經 50% 了

我要留言

立即登入留言