iT邦幫忙

2022 iThome 鐵人賽

DAY 7
1

來到第七天,我們利用這禮拜所學做一個台南美食地圖!
美食之都說是台南應該不為過吧 /images/emoticon/emoticon24.gif

那我是拿 TDX (Transport Data eXchange) 提供的 API 來做資料使用,它是交通部提供的免費 API 平台,大家有興趣可以去看看。但要注意的是,如果沒有註冊會員的話,一天呼叫上限是 50 次喔~

需求目標

先來制定一下這張地圖要有哪些需求:

  • 使用者定位
  • 可以切換全螢幕
  • 地圖上標記餐廳位置
  • 提供餐廳詳細資訊

一張基本的美食地圖該有的功能大概就這些了吧!那就可以開始動手做啦~

標記餐廳位置

首先,我們先把底層地圖設定好:

constructor(props) {
  super(props);
  this.state = {
    lng: 120,
    lat: 23.5,
    zoom: 7,
  };
  this.mapContainer = React.createRef();
}

componentDidMount() {
  const { lng, lat, zoom } = this.state;
  const map = new mapboxgl.Map ({
    container: this.mapContainer.current,
    style: 'mapbox://styles/mapbox/streets-v11',
    center: [lng, lat],
    zoom: zoom
  });
}

render() {
  return (
    <div>
      <div ref={this.mapContainer} className="map-container" />
    </div>
  );
}

再透過 Marker 將餐廳位置都標出來:(利用 map 輸出所有點)

data.map((d) => (
  new mapboxgl.Marker({
    scale: 0.8,
    color: "red"
  })
  .setLngLat([d.Position.PositionLon, d.Position.PositionLat])
  .addTo(map)
))

BTW,TDX 給的資料格式長這樣:

然後你就會獲得一張充滿紅色標點的地圖啦~

因為我們還沒學到 Layer,所以 Marker 就先全部標出來了,之後會教大家怎麼使用 Layer 做群集 (就是會長的比較漂亮啦,不會有密集恐懼症嗯嗯嗯)

提供餐廳資訊

那我們不可能就這樣丟給使用者吧,一堆紅點誰知道哪家是哪家 ಠ▃ಠ
這個時候 Popup 就派上用場了!
我們只要把餐廳的詳細資訊丟給它就好了,耶~:

data.map((d) => (
  new mapboxgl.Marker({
    scale: 0.8,
    color: "red"
  })
  .setLngLat([d.Position.PositionLon, d.Position.PositionLat])
  .setPopup(new mapboxgl.Popup({  // add restaurant detail
    maxWidth: "500px"
  }).setHTML(`
    <div class="res-detail-intro">
      <img class="res-pic" src=${d.Picture.PictureUrl1 || "https://www.bomb01.com/upload/news/original/c95e0d21eda50ebc16d5f8ef568f60a7.png"} />
      <div>
        <div class="res-title-txt">${d.RestaurantName}</div>
        <div class="res-detail-txt">營業時間:${d.OpenTime}</div>
        <div class="res-detail-txt">地址:${d.Address}</div>
        <div class="res-detail-txt">電話:${d.Phone}</div>
      </div>
    <div>
  `)) 
  .addTo(map)
))

因為有些餐廳沒有照片,所以我放了一張圖片替代這種狀況:

圖片來源:https://www.bomb01.com/article/50295

點擊 Marker 你就會看到跳出餐廳資訊了,看起來有模有樣了吧!

加入小工具

最後,我想讓我的使用者可以依照現在所在位置去找最近的餐廳,加入定位的小工具就可以了:

map.addControl(new mapboxgl.FullscreenControl());
map.addControl(new mapboxgl.GeolocateControl({
  positionOptions: {
    enableHighAccuracy: true
  },
  trackUserLocation: true,
  showUserHeading: true
}));

順便也加上切換全螢幕的按鈕給它:

你的美食地圖就完成啦!

Github 完整程式碼

過了一週不知道你有沒有跟我一樣愛上 Mapbox 的介面了 ><
明天開始會繼續介紹 API,希望我的學習速度能跟上發文 ... /images/emoticon/emoticon70.gif

Reference


上一篇
Day 06 - 給地圖加上彈跳窗
下一篇
Day 08 - Events (1):Interaction
系列文
打造你的主題地圖!Mapbox 也可以!(ft. React)30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言