寫在前頭
前端接案 re-spec,最近再開,「JavaScript 作品實戰直播班」也開始在解決每週作業,loading 比我想像中重,每天都在克服自己對 JavaScript 新知識的心魔,及害怕自己做不出來的恐懼,算是過著十分充實的生活,只能一直告訴自己,撐過去就是我的了!所以文還是要寫,把記憶體釋放一些(笑,接下來就進入本篇的內容了,Let's Go!(?
本篇記錄,會講到如何做出縣市及鄉鎮區連動的選單,還有定位至該鄉鎮區
讓縣市選單運作
連動選單比想像中難實作,參考了不少人的作品,才總算寫出來,先看看完整的程式碼:
const countySelector = document.querySelector('.countyList');
function addCountyList(){
let allCounty = [];
let countyStr='';
countyStr += '<option>請選擇縣市</option>'
for(let i=0;i<data.length;i++){
const countyName = data[i].properties.county;
if(allCounty.indexOf(countyName) == -1 && countyName !== ''){
allCounty.push(countyName);
countyStr += `<option value="${countyName}">${countyName}</option>`
}
}
countySelector.innerHTML = countyStr;
}
countySelector.addEventListener('change', addTownList);
const townSelector = document.querySelector('.townList');
townSelector.innerHTML = `<option value="">請選擇鄉鎮區</option>`;
function addTownList(e){
let countyValue = e.target.value;
let townStr = `<option value="">請選擇鄉鎮區</option>`;
let allTown = [];
let newTownList = '';
for (let i = 0; i < data.length; i++) {
let countyMatch = data[i].properties.county;
if (countyValue == countyMatch) {
allTown.push(data[i].properties.town);
}
}
newTownList = new Set(allTown);
newTownList = Array.from(newTownList);
for (let i = 0; i < newTownList.length; i++) {
townStr += `<option value="${newTownList[i]}">${newTownList[i]}</option>`
}
townSelector.innerHTML = townStr;
townSelector.addEventListener('change', geoTownView);
}
接下來分段來看,以下是 HTML 的部分:
<div class="areaList">
<select name="" id="" class="countyList">
</select>
<select name="" id="" class="townList">
</select>
</div>
在 HTML 裡我們定義了兩個 select,分別代表縣市及鄉鎮選單,接下來看到 JavaScript 的部分:
// 先宣告變數來選取代表縣市的 select
const countySelector = document.querySelector('.countyList');
// 使用函式來把縣市的資料取出來
function addCountyList(){
let allCounty = [];
let countyStr='';
countyStr += '<option>請選擇縣市</option>'
for(let i=0;i<data.length;i++){
// 取出 data 資料裡的縣市名稱
const countyName = data[i].properties.county;
// 這段的意思是,如果在 allCounty 這個陣列裡找不到 countyName,且 countyName 不為空字串,就把 countyName 放進 allCounty 這個陣列裡
if(allCounty.indexOf(countyName) == -1 && countyName !== ''){
allCounty.push(countyName);
// 把縣市名字串累加
countyStr += `<option value="${countyName}">${countyName}</option>`
}
}
// 並把縣市名字串累加的結果用 innerHTML 放進 countySelector 裡
countySelector.innerHTML = countyStr;
}
// 對 countySelector 進行監聽,當 countySelector change 時,執行 addTownList 函式
countySelector.addEventListener('change', addTownList);
我們就可以看到縣市的選單了。
讓縣市、鄉鎮區選單連動
接下來我們來實作鄉鎮區名的部分,看到 JavaScript 的部分:
// 一樣先宣告變數來選取代表鄉鎮區的 select
const townSelector = document.querySelector('.townList');
townSelector.innerHTML = `<option value="">請選擇鄉鎮區</option>`;
// 使用函式並帶入參數 e 來取得鄉鎮區的名字
function addTownList(e){
// 先取得縣市 select 中的 vallue,也就是縣市的名稱
let countyValue = e.target.value;
let townStr = `<option value="">請選擇鄉鎮區</option>`;
let allTown = [];
let newTownList = '';
// 然後用迴圈來取得符合條件的鄉鎮區名
for (let i = 0; i < data.length; i++) {
//先宣告 countyMatch 為 data 資料中的縣市名
let countyMatch = data[i].properties.county;
//用 if 來判斷,如果縣市 select 的值跟 data 資料裡的縣市名相同,就把所有的鄉鎮區名 push 到 allTown 這個陣列裡
if (countyValue == countyMatch) {
allTown.push(data[i].properties.town);
}
}
// 然後使用 Set 方法來產生一個集合讓陣列元素不會重複
newTownList = new Set(allTown);
// 再從剛才的集合產生陣列
newTownList = Array.from(newTownList);
for (let i = 0; i < newTownList.length; i++) {
// 把鄉鎮區名累加成字串
townStr += `<option value="${newTownList[i]}">${newTownList[i]}</option>`
}
// 並把鄉鎮區名字串累加的結果用 innerHTML 放進 townSelector 裡
townSelector.innerHTML = townStr;
// 對 townSelector 進行監聽,當 townSelector change 時,執行 geoTownView 函式
townSelector.addEventListener('change', geoTownView);
}
此時縣市及鄉鎮區的選單就可以連動了!未選取縣市時,無法顯示鄉鎮區,選取了縣市,才能接著選鄉鎮區。
選取縣市及鄉鎮區後定位至該鄉鎮區
現在我們要實作選取縣市及鄉鎮區,地圖會定位至該鄉鎮區,JavaScript 的部分如下:
function geoTownView(e) {
// 先取得鄉鎮區 select 中的 vallue,也就是鄉鎮區的名稱
let town = e.target.value;
let townLatLng = [];
let county = '';
for (let i = 0; i < data.length; i++) {
// 宣告變數取得 data 裡的鄉鎮區、縣市名稱及其經緯度
let townTarget = data[i].properties.town;
let countyTarget = data[i].properties.county;
let lat = data[i].geometry.coordinates[0];
let lng = data[i].geometry.coordinates[1];
// 比較鄉鎮區名及縣市名,如果兩者皆符合,則取得鄉鎮區的經緯度
if (townTarget == town && countyTarget == countySelector.value) {
// 並把經緯度賦值到變數 townLatLng
townLatLng = [lng, lat];
// 宣告變數 county 等於 data 裡的縣市資料
county = data[i].properties.county;
}
}
// 把鄉鎮經緯度代入,並設定 zoom 值為 17(此可依需求調整)
map.setView(townLatLng, 17);
// 把上面宣告的 town 及 county 變數帶入 renderList() 函式中
renderList(town,county);
}
// 此函式為下篇內容,我們下次再聊
function renderList(town,county){}
這一段寫完,我們只要選好縣市及鄉鎮區,就會飛到該鄉鎮區了~
最後我們來簡單的美化 select
我們在 CSS 加上下面這段,select 就美觀多了~
.areaList{
display:flex;
justify-content: center;
flex-wrap: wrap;
}
.countyList, .townList{
width:80%;
height: 30px;
border-radius: 5px;
border:1.3px solid #072e00;
}
.countyList{
margin-bottom:10px;
}
.countyList option{
text-align: center;
}
本週打完收工!我們下次見~