Vue_ 口罩地圖(實作)

執行共分為四步驟

  • 取得
  • 篩選
  • 配對
  • 顯示
  1. 取得API資料後(mounted)放置data變數裡,並使用leaflet語法串接地圖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

mounted() {
const url =
"https://raw.githubusercontent.com/kiang/pharmacies/master/json/points.json";
this.$http.get(url).then(response => {
this.data = response.data.features;
console.log("<data>"+JSON.stringify(this.data));
this.updateMarker(); //取得資料後執行更新
});

osmap = L.map("map", {
center: [25.03, 121.55],
zoom: 16
});

L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}", {
foo: "bar",
attribution:
'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
maxZoom: 18
}).addTo(osmap);

L.marker([25.03, 121.55]).addTo(osmap);
}
};
  1. 載入台灣城市JSON檔案,匯出Select選擇欄(縣市+區域)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

<div class="search-bar p-2">
<div class="form-group d-flex">
<label for="city" class="mr-2 col-form-label">縣市</label>
<div class="flex-fill">
<select class="form-control"
id="city"
v-model="select.city"
@change="select.area = ''"
>
<!-- 當選擇其他選項時,就會觸發change裡的指令 -->
<option value>-- 請選擇縣市 --</option>
<option
v-for="item in cityName"
:value="item.CityName"
:key="item.CityName"
>{{ item.CityName }}</option>
</select>
</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div class="form-group d-flex">
<label for="area" class="mr-2 col-form-label">地區</label>
<div class="flex-fill">
<select class="form-control"
id="area"
v-if="select.city.length"
v-model="select.area"
@change="updateSelect"
>
<option value>-- 請選擇地區 --</option>
<option
:value="area.AreaName"
v-for="area in cityName.find((city) => city.CityName === select.city).AreaList"
:key="area.AreaName"
>{{ area.AreaName }}</option>
</select>
</div>
</div>
  1. 執行filter將Select選擇的區域做配對,媒合後顯示資料
1
2
3
4
5
6
7
8
9
10
11
methods: {
updateMarker() {
//取出區域
const pharmacies = this.data.filter(pharmacy => {
//如果data裡的area沒有資訊,則找出與data裡的city相同的縣市
if (!this.select.area) {
return pharmacy.properties.county === this.select.city;
}
//找出與data裡的area相同的區域
return pharmacy.properties.town === this.select.area;
});

緊接著利用forEach匯入地圖座標、顯示藥局資訊等功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

//利用forEach執行動作,取得座標+顯示內容
pharmacies.forEach(pharmacy => {
const { properties, geometry } = pharmacy;
const icon = properties.mask_adult || properties.mask_child ? icons.orange : icons.grey;
}

L.marker([
geometry.coordinates[1],geometry.coordinates[0],properties],{icon})
.addTo(osmap).bindPopup(`<h5>${properties.name}</h5>
電話: ${properties.phone}<br>
地址:<a href="https://www.google.com.tw/maps/place/${properties.address}" target="_blank">${properties.address}</a><br>
<small>資料更新時間:${properties.updated}</small>
<p>備註: ${properties.note}</p>
<hr>
<mark>口罩數量:<b>成人<ins>
${properties.mask_adult} </ins>個 / 兒童 <ins> ${properties.mask_child}</ins> 個
</b></mark><br>
`);
});
//上面執行的forEach是顯示初步取得(select選項)的地圖資訊,而非點擊後的

this.penTo(pharmacies[0]); //回傳入第一個藥局進入penTo下方的語法

},
  1. 最後一步是將取得資料顯示在頁面上,使用迴圈,並經由v-if判定是否符合縣市與區域的資料,顯示結果就會是select裡選擇的區域資料。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

<ul class="list-group text-dark">
<template v-for="(item, key) in data">

<!-- v-if符合條件才顯示 -->
<a class="list-group-item"
:key="key"
v-if="item.properties.county === select.city && item.properties.town === select.area"
:class="{ 'mask-highlight': !item.properties.mask_adult && !item.properties.mask_child}"
@click="penTo(item)"
>
<div class="d-flex align-items-baseline">
<i class="fas fa-hospital-symbol mr-1" style="font-size:18px;color:orange"></i>
<div class="info_title">{{ item.properties.name }}</div>
</div>
<div class="info_address">
<p class="mb-0">
地址:
<a :href="`https://www.google.com.tw/maps/place/${item.properties.address}`"
title="Google Map"
>{{ item.properties.address }}</a>
</p>
</div>

leaflet地圖工具

Leaflet 是一套適用於各種平台的 JavaScript 地圖繪製工具,可以呈現類似 Google 地圖的效果。要在網頁上呈現地圖,除了大多數人所熟知的 Google 地圖之外,Leaflet 也是一套很不錯的工具,它是一套開放原始碼的輕量級 JavaScript 網頁地圖函式庫,其所呈現的效果與 Google 地圖非常相似,主要的特色是使用簡單、速度快,並且跨平台,許多知名網站(如 GitHub 與 Flickr 等)都是使用 Leaflet 來呈現地圖。

實用功能

layerremove: 切換區域時移除舊的指標
1
2
3
4
5
6
7
8
9
// 當select切換區域時(@change)),就會觸發移除指標
updateSelect() {
osmap.eachLayer(layer => {
if (layer instanceof L.Marker) {
osmap.removeLayer(layer);
}
});
this.updateMarker();
},
panTo:點擊後會移動至指定位置並聚焦放大
1
2
3
4
5
6
7
8
9
10
penTo(item) {
const { properties, geometry } = item;
const icon = properties.mask_adult || properties.mask_child ? icons.orange : icons.grey;

//panTo的功用是點擊後會移動至指定位置並聚焦放大
osmap.panTo([
geometry.coordinates[1],
geometry.coordinates[0],
properties
]);
openPopup:自動彈跳藥局的“資訊文字”
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  L.marker([geometry.coordinates[1], geometry.coordinates[0]],{icon})
.addTo(osmap).bindPopup(
`<h5>${properties.name}</h5>
電話:${properties.phone}<br>
地址: <a href="https://www.google.com.tw/maps/place/${properties.address}" target="_blank">${properties.address}</a><br>
<small>資料更新時間:${properties.updated}</small>
<p>備註:${properties.note}</p>
<hr>
<mark>口罩數量:<b>成人有<ins>
${properties.mask_adult} </ins>個 / 兒童有 <ins> ${properties.mask_child}</ins> 個
</b></mark><br>
`
)
.openPopup();
//彈跳鼠標藥局的“資訊文字”
//這裡會顯示聚焦後(點擊後會放大)的資訊
}

實作成品

作品: 口罩搜尋地圖