執行共分為四步驟
- 取得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 © <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); } };
|
- 載入台灣城市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>
|
- 執行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下方的語法
},
|
- 最後一步是將取得資料顯示在頁面上,使用迴圈,並經由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 ]);
|
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(); //彈跳鼠標藥局的“資訊文字” //這裡會顯示聚焦後(點擊後會放大)的資訊 }
|
實作成品
作品: 口罩搜尋地圖