寫在前頭

前端接案 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;
}

本週打完收工!我們下次見~

資料補充


##口罩地圖 #六角學院 #台灣口罩地圖-2020 防疫要贏 #javascript #css #JavaScript 入門篇 - 學徒的試煉 #口罩地圖 #六角學院 #台灣口罩地圖-2020 防疫要贏 #javascript #css #JavaScript 入門篇 - 學徒的試煉







Related Posts

【單元測試的藝術】Chap 5: 隔離(模擬)框架

【單元測試的藝術】Chap 5: 隔離(模擬)框架

用 Python 自學資料科學與機器學習入門實戰:Scikit Learn 基礎入門

用 Python 自學資料科學與機器學習入門實戰:Scikit Learn 基礎入門

自動化測試 x Puppeteer - 玩偶QA參一咖 Day03

自動化測試 x Puppeteer - 玩偶QA參一咖 Day03



Comments