有個需求是要檢查某地址是否在某特定區域內, 於是思考使用 Google Maps API 來實做, 判斷的部分可以不需要 Google Maps 顯示, 但在測試或開發時, 若有可視的地圖會比較容易理解狀況, 也比較明白指定區域與指定位置的關係, 以下分為幾個部分來進行.
首先需要能繪製指定區域, 這個和程式沒有直接關係, 但透過 Google 的 MyMaps 比較好進行:
http://mymaps.google.com/
進入後, 建立新地圖, 出現 Google Maps 之後, 使用”畫一條線”的”新增內容或形狀”工具來進行區域的繪製:
一點一點地把區域點好後, 點回起點, 就可以產生一個封閉區域了, 再給予命名, 如以下範例:
這個部分可以隨時再進行區域的調整, 到自己滿意為止, 之後我們需要的其實是這個區域的多邊形座標點, 如何取得呢? 點擊新增圖層邊的三個點, 出現選單後, 選匯出成 KML:
就可以取得對應的 KML 檔案了, 打開 KML 檔中, 最重要的是找到座標點, 內容會是這樣的文字:
<coordinates>121.5437222,25.0416515,0.0 …… </coordinates>
這些座標點就是用來做這個指定區域的座標位置了, 接下來才真正要準備實作程式.
寫了一個小程式, 把這些座標點輸出成一串之後 Google Maps API Geometry 會用到的格式:
http://sample.diary.tw/36/tools.htm
我們將上面的 <coordinates> 中的字串, 填入上面小程式的 textarea 之後, 按下”產生區域多邊形座標”, 就可以得到像是這樣的內容:
{lat: 25.0416515, lng:121.5437222},
{lat: 25.0333111, lng:121.543529},
.....
先準備好到這裡, 之後參考這個部分可以進行多邊形繪製:
https://developers.google.com/maps/documentation/javascript/examples/polygon-simple
可以看到其中會需要的陣列就由上面小程式產生的內容填入即可, 記得, 在參考 google maps 的範例程式時, 在 initMap 中, 有個 center 參數和 zoom 參數, 要填入實際上你地圖的位置附近, 不然不會出現在地圖上, 如 google maps 範例內, 是百幕達三角洲地帶, 而且 zoom 是 5, 若是以台北市來看, 大約 zomm 是在 15或16 左右.
如範例: http://sample.diary.tw/36/map1.htm
主要程式碼為:
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 25.037828, lng: 121.547204},
zoom: 16,
});
var testAreaCoords = [
{lat: 25.0416515, lng:121.5437222},
{lat: 25.0333111, lng:121.543529},
{lat: 25.033116700000004, lng:121.5526271},
{lat: 25.036052399999996, lng:121.55267000000002},
{lat: 25.0374716, lng:121.55146840000002},
{lat: 25.038016, lng:121.5513396},
{lat: 25.0415348, lng:121.5474987},
{lat: 25.0416515, lng:121.5437222},
];
testArea = new google.maps.Polygon({
paths: testAreaCoords,
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 3,
fillColor: '#FF0000',
fillOpacity: 0.05
});
testArea.setMap(map);
接下來就是由指定的地址查找座標, 這個部分會用到 Google Maps API 中的 geocoder, 只需要將地址傳入, 就可以取得對應的座標了, 參考資料:
https://developers.google.com/maps/documentation/javascript/geocoding#GeocodingStatusCodes
程式碼不多, 參考範例:
http://sample.diary.tw/36/map2.htm
輸入地址就可以取得座標(經緯度)
主要程式碼如下(注意, geocoder 是用 callback 方式回傳):
function initMap() {
geocoder = new google.maps.Geocoder();
}
function codeAddress() {
var address = document.getElementById("address").value;
geocoder.geocode({
'address': address
}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
alert("lat=" + results[0].geometry.location.lat() + ",lng=" + results[0].geometry.location.lng());
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
最後就是利用一個很重要的判斷式來判斷某地址(已取得座標)是否在指定區域內, containsLocation() 參考:
https://developers.google.com/maps/documentation/javascript/examples/poly-containsLocation
上面的範例是用點擊地圖的方式, 看點擊的位置是否在百幕達三角洲內, 是的話就是紅色 marker, 不是的話, 就用綠色 marker.
來改寫一下程式碼, 就可以達成判斷指定的地址是否在指定的區域內了, 如範例:
http://sample.diary.tw/36/map3.htm
主要程式碼:
// check if position in polygon
if(google.maps.geometry.poly.containsLocation(results[0].geometry.location, testArea)){
alert("在指定區域內");
}else{
alert("不在指定區域內");
}
總結一下:
- 先製作指定區域座標陣列(多邊形用)
- 使用 geocoder 取得指定的地址轉換為座標
- 使用 google.maps.geometry.poly.containsLocation 來判斷2.是否在1.裡面
PS. 記得要先到 https://console.developers.google.com/ 建立一個可以使用 Google Maps API 的應用程式, 並建立對應的 browser key 放到上面的程式碼中, 以順利執行你的 web 應用程式.