
| 知識點 | 使用說明 | 
|---|---|
| linear-gradient | 設定線性的漸層背景 | 
| flexbox | 在此用於製作卡片的排版且有RWD效果 | 
| 知識點 | 使用說明 | 
|---|---|
| async / await | 簡化promise以及對多個 Promise 物件執行某些操作 | 
| fetch() | 使用 fetch 發送請求 ( request ) | 
| Object.keys() | 回傳一個包含物件中所有可列舉之屬性的陣列 | 
| find() | 回傳第一個滿足所提供之測試函式的元素值,否則回傳 undefined | 
| map() | 遍歷陣列中的元素 | 
| slice() | 為原陣列選擇之 begin 至 end(不含 end)部分的淺拷貝(shallow copy) | 
| padStart() | 將編號的前面自動補0 | 
| indexOf() | 回傳給定元素於陣列中第一個被找到之索引,若不存在則回傳 -1 | 
 <h1>Pokedex</h1>
    <div class="container" id="container">
        <!-- 1 -->
        <div class="pokemon" style="background-color: red;">
            <div class="img-container">
                <img src="..." alt="...">
            </div>
            <div class="info">
                <span class="number">#001</span>  
                <span class="name">皮卡丘</span>
                <small class="type"> <span>電</span> </small>
            </div>
        </div>
        
        <!-- 2 -->
        <div class="pokemon" style="background-color: red;">
            <div class="img-container">
                <img src="..." alt="...">
            </div>
            <div class="info">
                <span class="number">#002</span>
                <span class="name">妙蛙草</span>
                <small class="type"> <span>草</span> </small>
            </div>
        </div>
        
        <!-- 3 -->
        <div class="pokemon" style="background-color: red;">
            <div class="img-container">
                <img src="..." alt="...">
            </div>
            <div class="info">
                <span class="number">#003</span>
                <span class="name">傑尼龜</span>
                <small class="type"> <span>水</span> </small>
            </div>
        </div>
    </div>
* {
  box-sizing: border-box;
}
body {
  background: #efefbb;
  background: linear-gradient(to right, #d4d3dd, #efefbb);
  margin: 0;
  padding: 0;
  display: flex; /*讓內容在viewport的中間*/
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
h1 {
  letter-spacing: 3px;
}
設定好後呈現如下
接下來要把圖片變成卡片的排版,從縱向變成橫向,呈現大概會如下圖這樣
卡片內部
.pokemon {
  background-color: #eee;
  border-radius: 10px;
  box-shadow: 0 3px 15px rgba(100, 100, 100, 0.5);
  margin: 10px;
  padding: 20px;
  text-align: center;
}
.pokemon .img-container {
  background-color: rgba(255, 255, 255, 0.6);
  border-radius: 50%;
  width: 120px;
  height: 120px;
  margin: 5px auto;
  text-align: center;
}
.pokemon .img-container img {
  max-width: 90%;
  margin-top: 20px;
}
.pokemon .info .number {
  background-color: rgba(0, 0, 0, 0.1);
  border-radius: 10px;
  padding: 5px 10px;
  font-size: 14px;
}
.pokemon .info .name {
  margin: 15px 0 7px;
  letter-spacing: 1px;
}
樣式的部分大致上是完成了,要來處理今天的核心
變數宣告
const container = document.getElementById("container");
const pokemon_count = 150; //要抓的寶可夢的總數
const colors = {
  fire: "#FDDFDF",
  grass: "#DEFDE0",
  electric: "#FCF7DE",
  water: "#DEF3FD",
  ground: "#f4e7da",
  rock: "#d5d5d4",
  fairy: "#fceaff",
  poison: "#98d7a5",
  bug: "#f8d5a3",
  dragon: "#97b3e6",
  psychic: "#eaeda1",
  flying: "#F5F5F5",
  fighting: "#E6E0D4",
  normal: "#F5F5F5",
會設定那麼多顏色,是之後要去為不同寶可夢的類型去做分類,同個類型就同種顏色
API
接下來要從外部的API(點此)取得POKEMON的資料和圖片
可以透過ID、類型、能力、種類來客製化我們的API,在這邊我們選用ID的方式來設計
const fetchPokemons = async () => {
  for (let i = 1; i <= pokemon_count; i++) {
    await getPokemon(i); //這裡i代表id
  }
};
const getPokemon = async (id) => {
  const url = `https://pokeapi.co/api/v2/pokemon/${id}`;
  const res = await fetch(url);
  const data = await res.json();
  
   createPokemonCard(data);
   
     console.log(data);  //請看下圖
};
fetch() 是一個全域的方法,需要傳入一個參數,也就是資料的 URL,會回傳一個包含 response 的 promise,這裡我們用async await的讓語法更簡潔易讀
接著把data印出來,就是一堆密密麻麻的資料啦~okok代表我們成功獲取到資料了
接下來我們要回到HTML把部分預先寫好的程式碼先註解掉,因為要直接用JS來操控,HTML只需留下以下這部分即可
  <h1>Pokedex</h1>
    <div class="poke-container" id="poke-container"></div>
建立pokemon元素
const createPokemonCard = (pokemon) => {
  const pokemonEl = document.createElement("div");  //建立元素
  pokemonEl.classList.add("pokemon");  
  
  const pokemonInnerHTML = `
  <div class="img-container">
  <img src="省略不寫" alt="pikachu">
  </div>
<div class="info">
  <span class="number">#001</span>
  <span class="name">Pikachu</span>
  <small class="type"> <span>electric</span> </small>
</div>
    `;
   
  pokemonEl.innerHTML = pokemonInnerHTML;
  container.appendChild(pokemonEl);
  
};
把img-container的內容放到樣板字串中,設定好呈現如下,非常多隻皮卡丘,每張圖都一樣,原因是我在省略的圖片網址中先寫死的,接著要把它成動態呈現,依照不同id代表不同圖片來完成
動態呈現(編號、名稱、圖片、類型、顏色)
const mainType = Object.keys(colors);
const createPokemonCard = (pokemon) => {
  const pokemonEl = document.createElement("div");
  pokemonEl.classList.add("pokemon");
  //編號
  const id = pokemon.id.toString().padStart(3, "0");  //補0在每個編號前面,共3位數
  //名稱
  const name = pokemon.name[0].toUpperCase() + pokemon.name.slice(1); //第一個字母大寫,其餘都小寫
  //類型
  const pokemonType = pokemon.types.map((type) => type.type.name); 
  const type = mainType.find((type) => pokemonType.indexOf(type) != -1); //不等於-1代表有找到值
  //顏色
  const color = colors[type];
  pokemonEl.style.backgroundColor = color;
  // 圖片
  const pokemonInnerHTML = `
  <div class="img-container">
  <img src="https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${pokemon.id}.png" alt="${name}">
  </div>
  
<div class="info">
  <span class="number">#${id}</span>
  <span class="name">${name}</span>
  <small class="type"> <span>${type}</span> </small>
</div>
    `;
    
  pokemonEl.innerHTML = pokemonInnerHTML;
  container.appendChild(pokemonEl);
};
fetchPokemons();
設定好呈現如下
以上是這次的project,若有解說不夠詳盡或是錯誤歡迎指教,感激不盡!
附上codepen連結 https://codepen.io/hangineer/pen/zYjJqyE
50 Projects In 50 Days - HTML, CSS & JavaScript
寶可夢官網
本篇用到很多陣列處理方法,像是find() 、 slice() 、 map() 、 indexOf(),還有ferch API ,還會連貫到 promise、async await 的概念,有很多重點中的重點,剛好藉由這個賽project而有再次練習的機會,覺得挺好的~
今天也是最後一篇文了,很開心自己做到了對自己的承諾ヽ(✿゚▽゚)ノ,這30天各種酸甜苦辣,簡單一點的project可以3個小時內完成並打完文章,複雜一點的甚至3-5個小時都有,加上沒有庫存文章(下次參賽要記得庫存!!),所以常常在有時間壓力下趕緊把文章發布出去,過程中最困難的無非就是自律以及把project梳理成文字來呈現其脈絡,參加鐵人賽剛好是一個很好的自我訓練,也謝謝IT邦幫忙提供了這個機會,鐵人賽我們後會有期