iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 16
0

前言

昨天我們已經進行了三個關卡,今天要繼續推進剩下的兩關!準備好了嗎? Let's Go!

第四關:最終版型

融合昨天我們想到的三個步驟:用判斷式判斷要彈出什麼文字、渲染畫面,還有打造出使用者能輸入的欄位,利用監聽按鈕讓它進行後續的動作,甚至可以讓它不同狀態用不同顏色顯示。只差把所有觀念融合在一起,就可以完成最後的版型!

設計圖如下(六角學院的表頭圖片網址為"https://imgur.com/QdUuOGZ.png")

如何做清除的部分等一下再下面我們會講到,可以先自己想想看,或上網找找其他人的分享。真的寫不出來先跳過也沒有關係!現在,讓我們一起動手寫寫看。先別偷看底下的答案喔!

  • html
<div class = "wrap">
  <div class = "header">
    <img src="https://imgur.com/QdUuOGZ.png">
    <h1>大 AI 數據之 BMI 體重計</h1>
  </div>
  <div class = "main">
    <div class = "typeForm">
      <label for = "cm" class = "titleCm">身高 cm</label>
      <input type = "text" name = "cm" placeholder = "請輸入身高" id = "cm" class = "height">
      <label for = "kg" class = "titleKg">體重 kg</label>
      <input type = "text" name = "kg" placeholder = "請輸入體重" id = "kg" class = "weight">
      <input type = "submit" value = "確認" class = "cfmbtn">
      <input type = "submit" value = "全部清除" class = "clearbtn">
      </div>
      <div class = "recordList">
        <h2>BMI 紀錄</h2>
        <ul class = "list">
        </ul>
      </div>
  </div>
</div>
  • css(記得加上 css reset)
.wrap h1, input, .recordList h2, #count{
  font-family: Microsoft JhengHei;
  font-size: 20px;
}

.wrap{
  width: 1920px;  
  line-height: 1.5;
}

.wrap img{
  margin-top: 40px;
  margin-left: 360px;
  width: 126px;
  height: 48px;
  background: transparent url('img/logo_工作區域 1.png') 0% 0% no-repeat padding-box;
  opacity: 1;
}

.wrap h1{
  font-size: 36px;
  color: #3D82AD;
  text-align: center;
}

.typeForm{
  margin-top: 50px;
  margin-left: 360px;
  padding: 10px;
  line-height: 3;
  width: 1200px;
  background: #3D82AD; 
  display: flex;
  flex-direction: column;
  align-items: center;
}

.height, .weight{
  width: 384px;
}

input{
  border-width: 1.5px;
  border-color: #B1D7FB;
  border-radius: 5px;
  padding: 5px;
}

.cfmbtn, .clearbtn{
  width: 150px;
  color: #fff;
  background-color: #3D82AD;
  padding: 7px;
}

.cfmbtn{
  margin-top: 20px;
}

.clearbtn{
  margin-top: 10px;
  margin-bottom: 20px;
}

.cfmbtn:hover, .clearbtn:hover{
  background-color:#B1D7FB;
}

.titleCm, .titleKg{
  font-size: 16px;
  font-family:Microsoft JhengHei;
  color: #fff;
}

.recordList h2{
  font-size: 25px;
  text-align: center;
  color: #3D82AD;
  margin: 50px;
  display : block;
}

.list{
  display: flex;
  flex-direction: column;
  align-items: center;
}

.listItem{
	line-height: 27px;
	border: #3d82ad solid 2px;
	border-radius: 2px;
	width: 22rem;
	color: #3d82ad;
	font-weight: 600;
  margin: 10px;
}

.blue, .green, .yellow, .orange, .pink, .red{
  font-size: 24px;
  font-family : Microsoft JhengHei;
  text-align: center;
  padding: 10px;
}
.blue {
	color: #0000ff;
}
.green {
	color: #00aa00;
}
.yellow {
	color: #daa520;
}
.orange {
	color: #ff8800;
}
.pink {
	color: #FF69B4;
}
.red {
	color: #ff0000;
}

.list li{
  line-height: 3;
  font-size: 16px;
  font-family : Microsoft JhengHei;
  text-align: center;
}
  • js
const height = document.querySelector('.height');
const weight = document.querySelector('.weight');
const cfm = document.querySelector('.cfmbtn');
const clearbtn = document.querySelector('.clearbtn');
const list = document.querySelector('.list');

let data = [];

function calculationBMI(){
  const h = Number(height.value);
  const w = Number(weight.value);
  const bmi = (w / Math.pow(h / 100, 2)).toFixed(2);
  if(bmi>=35){
      add("red","重度肥胖",bmi);
    }else if(bmi>=30 && bmi<35){
      add("pink","中度肥胖",bmi);
    }else if(bmi>=27 && bmi<30){
      add("orange","輕度肥胖",bmi);
    }else if(bmi>=24 && bmi<27){
      add("yellow","過重",bmi);
    }else if(bmi>=18.5 && bmi<24){
      add("green","正常",bmi);
    }else if (bmi>=0 && bmi<18.5){
      add("blue","過輕",bmi);
    }else if (bmi <0){
      alert("錯誤");
    }
    height.value = ""; //清空使用者資料
    weight.value = ""; //清空使用者資料
}

function add(color, status, bmi){
    data.push({
    height: height.value,
    weight: weight.value,
    bmi: bmi,
    status: status,
    color: color
  });
  display();
}

function reset(){
  list.innerHTML = ""; //新增這句,才能讓.list中的資料被清除
}

function display(){
    let str = "";
    data.forEach(function(item){  
      str += `
        <div class = listItem>
          <h3 class="mb-3 text-center ${item.color}">${item.status}</h3>
          <ul>
             <li>BMI:${item.bmi}</li>
             <li>height:${item.height}</li>
             <li>weight:${item.weight}</li>
          </ul>
      </div> `
    });
      list.innerHTML = str;
}

cfm.addEventListener("click",calculationBMI); 
clearbtn.addEventListener("click",reset); 

解釋一下 const bmi = (w/Math.pow(h/100,2)).toFixed(2); 這句。前面第一關的時候,沒有提到這個用法。 Math.pow 的語法如下: Math.pow(基數, 讓基數成幾次) ,換句話說就是 w/(h/100)*(h/100) 一模一樣的意思。而 .toFixed(2) 可以讓小數點取到第二位。要使用原本第一關的寫法也可以,這邊單純是做優化。

不同狀態的樣式部分,直接設在一開始判斷的地方,讓畫面看起來簡潔一點。清除的部分,需要監聽清除按鍵,並設定一個清除的函式讓它執行。因為清除的目的,是要讓下方 list 中的東西消失,直觀想到的是讓它變為空字串。如果有沒有講解到的部分,歡迎留言提問。另外,每個人寫出來的可能不太一樣,也歡迎分享你的寫法喔!

第五關:主委加碼

來我們繼續送幸福(???)

其實到第四關為止已經把 BMI 計算機做出來了,但現在想要再加上一個小小的計算平均值的功能,優化使用者體驗。該怎麼處理呢?

想好了嗎?我要公布答案囉!

  • html
    在 BMI 紀錄和 list 的中間加入讓平均值的位置:
        <h2>BMI 紀錄</h2>
        <h3 class = average> <!--增加這句。總計測量<span></span>次,平均 BMI 為<span></span>--></h3>
        <ul class = "list">
        </ul>
  • css
    增加平均值的 css 樣式:
.average{
  font-size: 25px;
  font-family : Microsoft JhengHei;
  text-align: center;
  color: red;
}
  • js
    加入的東西比較多,所以我直接貼完整的程式碼上來:
var height = document.querySelector('.height');
var weight = document.querySelector('.weight');
var cfm = document.querySelector('.cfmbtn');
var clearbtn = document.querySelector('.clearbtn');
var recordList = document.querySelector('.recordList');
var list = document.querySelector('.list');
var average = document.querySelector('.average');
var totalBMI = 0; //要得出 BMI 平均值,要把總數除以次數 data.length ,宣告一開始 BMI 總數為 0
var averageBMI = 0; //宣告一開始 BMI 平均值為 0

var data = [];

function calculationBMI(){
  var h = Number(height.value);
  var w = Number(weight.value);
  var bmi = (w / Math.pow(h / 100, 2)).toFixed(2);
  if(bmi>=35){
      add("red","重度肥胖",bmi);
    }else if(bmi>=30 && bmi<35){
      add("pink","中度肥胖",bmi);
    }else if(bmi>=27 && bmi<30){
      add("orange","輕度肥胖",bmi);
    }else if(bmi>=24 && bmi<27){
      add("yellow","過重",bmi);
    }else if(bmi>=18.5 && bmi<24){
      add("green","正常",bmi);
    }else if (bmi>=0 && bmi<18.5){
      add("blue","過輕",bmi);
    }else if (bmi <0){
      alert("錯誤");
    }
    height.value = ""; 
    weight.value = ""; 
}

function add(color, status, bmi){
    data.push({
    height: height.value,
    weight: weight.value,
    bmi: bmi,
    status: status,
    color: color
  });

  sum(bmi); //執行 sum 的函式,把 bmi 放進去跑
  display(); //跑完執行 display 函式
}

function sum(bmi){
  totalBMI += Number(bmi); 
  averageBMI = (totalBMI / data.length).toFixed(2);
}

function reset(){
  data = [];
  list.innerHTML = ""; 
  average.innerHTML = "";
}

function display(){
    var str = "";
    data.forEach(function(item){  
      str += `
        <div class = listItem>
          <h3 class="mb-3 text-center ${item.color}">${item.status}</h3>
          <ul>
             <li>BMI:${item.bmi}</li>
             <li>height:${item.height}</li>
             <li>weight:${item.weight}</li>
          </ul>
      </div> `
    });
      list.innerHTML = str;
      average.innerHTML = `<h3>總計測量 ${data.length} 次,平均 BMI 為 ${averageBMI}`;
}

cfm.addEventListener("click",calculationBMI) 
clearbtn.addEventListener("click",reset) 

相關的注意事項已經直接寫在註解裡了,如果寫起來有哪個觀念不太熟悉,記得回去複習之前的文章喔。希望這兩天的練習對你有所幫助!

學習與參考資料

JS 學徒特訓班教學影片及練習題 20-21 關
Math.pow():https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Math/pow
Number.prototype.toFixed():https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed


上一篇
15 來寫 BMI 計算機 (上)
下一篇
17 D3.js 繪製圖表
系列文
花三十天找到 JavaScript 沙漠中的綠洲35
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言