使用 geojson.io 在 Google Maps 上建立地理柵欄

使用 geojson.io 在 Google Maps 上建立地理柵欄

在開發需要「位置範圍判斷」的功能時,地理柵欄(Geofencing)是很常見的需求。例如:判斷玩家是否進入指定活動區域、確認使用者是否位於服務範圍內,或是根據所在位置觸發不同的互動內容。

如果直接在程式碼裡手動輸入經緯度,不但不直覺,也很容易因為座標順序或邊界不精準而出錯。這時候可以使用 geojson.io 先在地圖上畫出範圍,再把結果匯出成 GeoJSON,最後放到 Google Maps 裡顯示與判斷。

這篇文章會介紹如何使用 geojson.io 建立地理柵欄,並示範如何將 GeoJSON 套用到 Google Maps JavaScript API 中。

什麼是地理柵欄

地理柵欄可以想成是在地圖上畫出一個虛擬邊界。當某個座標進入、離開或停留在這個範圍內時,系統就可以根據判斷結果執行對應邏輯。

常見的應用情境包含:

  • 活動場域範圍判斷
  • 外送或物流服務區域限制
  • 遊戲中的區域任務觸發
  • 公司、校園或展場的定位互動
  • 特定行政區或商圈範圍標記

在 Google Maps 上實作地理柵欄時,最常用的圖形是多邊形(Polygon)。只要有一組多邊形座標,就能在地圖上畫出範圍,並判斷某個位置是否落在範圍內。

為什麼使用 geojson.io

geojson.io 是一個線上 GeoJSON 編輯工具,可以直接在地圖上繪製點、線、多邊形,並即時產生 GeoJSON 內容。對於需要快速建立地理範圍的開發流程來說,它非常方便。

使用 geojson.io 的好處包含:

  • 可以直接在地圖上視覺化繪製範圍
  • 不需要手動查詢每個邊界座標
  • 支援 GeoJSON 格式,方便與前後端交換資料
  • 可以快速調整多邊形邊界
  • 適合用來製作原型或建立初始範圍資料

GeoJSON 本身是一種常見的地理資料格式,能描述點(Point)、線(LineString)、多邊形(Polygon)等地理物件。Google Maps 雖然不是直接以 GeoJSON 作為主要操作格式,但可以透過 Data Layer 載入 GeoJSON,也可以將 GeoJSON 座標轉換成 Google Maps 使用的座標格式。

使用 geojson.io 繪製地理柵欄

首先開啟 geojson.io

1
https://geojson.io/

進入網站後,可以在左側看到地圖,右側則會顯示目前產生的 GeoJSON 內容。接著按照以下步驟操作:

  1. 使用搜尋或縮放功能移動到目標區域
  2. 選擇多邊形繪製工具
  3. 在地圖上依序點選地理柵欄的邊界位置
  4. 點回起始點或完成繪製,形成封閉多邊形
  5. 觀察右側產生的 GeoJSON 內容

完成後,右側會產生類似以下的 GeoJSON:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"name": "demo-geofence"
},
"geometry": {
"coordinates": [
[
[121.562712, 25.033968],
[121.565148, 25.033968],
[121.565148, 25.031856],
[121.562712, 25.031856],
[121.562712, 25.033968]
]
],
"type": "Polygon"
}
}
]
}

這裡有一個很重要的細節:GeoJSON 的座標順序是 [longitude, latitude],也就是 [經度, 緯度]。但 Google Maps 常見的座標物件格式是 { lat, lng },也就是緯度在前、經度在後。實作時如果沒有轉換,範圍會出現在錯誤的位置。

在 Google Maps 上顯示 GeoJSON

如果只是要把 GeoJSON 顯示在 Google Maps 上,可以使用 Google Maps JavaScript API 的 Data Layer。Data Layer 可以直接讀取 GeoJSON,並將其中的地理物件畫在地圖上。

以下是一個簡化範例:

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<div id="map" style="height: 500px;"></div>

<script>
const geofenceGeoJson = {
type: "FeatureCollection",
features: [
{
type: "Feature",
properties: {
name: "demo-geofence"
},
geometry: {
coordinates: [
[
[121.562712, 25.033968],
[121.565148, 25.033968],
[121.565148, 25.031856],
[121.562712, 25.031856],
[121.562712, 25.033968]
]
],
type: "Polygon"
}
}
]
};

function initMap() {
const map = new google.maps.Map(document.getElementById("map"), {
center: { lat: 25.032912, lng: 121.56393 },
zoom: 16
});

map.data.addGeoJson(geofenceGeoJson);
map.data.setStyle({
fillColor: "#4285f4",
fillOpacity: 0.25,
strokeColor: "#1a73e8",
strokeWeight: 2
});
}
</script>

<script
async
defer
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
</script>

這種方式適合用來顯示範圍,特別是當 GeoJSON 可能包含多個 Feature,或是你希望保留 GeoJSON 原始結構時會很方便。

判斷座標是否在地理柵欄內

如果要做「某個座標是否位於地理柵欄內」的判斷,可以使用 Google Maps Geometry Library 提供的 google.maps.geometry.poly.containsLocation()

由於 containsLocation() 需要的是 Google Maps 的 Polygon 物件,因此要先把 GeoJSON 的 [lng, lat] 座標轉換成 { lat, lng }

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<div id="map" style="height: 500px;"></div>

<script>
const geofenceGeoJson = {
type: "Feature",
properties: {
name: "demo-geofence"
},
geometry: {
type: "Polygon",
coordinates: [
[
[121.562712, 25.033968],
[121.565148, 25.033968],
[121.565148, 25.031856],
[121.562712, 25.031856],
[121.562712, 25.033968]
]
]
}
};

function createPolygonFromGeoJson(feature) {
const paths = feature.geometry.coordinates[0].map(([lng, lat]) => ({
lat,
lng
}));

return new google.maps.Polygon({ paths });
}

function initMap() {
const map = new google.maps.Map(document.getElementById("map"), {
center: { lat: 25.032912, lng: 121.56393 },
zoom: 16
});

const geofencePolygon = createPolygonFromGeoJson(geofenceGeoJson);
geofencePolygon.setMap(map);

const userLocation = new google.maps.LatLng(25.032912, 121.56393);
const isInside = google.maps.geometry.poly.containsLocation(
userLocation,
geofencePolygon
);

console.log(isInside ? "位於地理柵欄內" : "位於地理柵欄外");
}
</script>

<script
async
defer
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=geometry&callback=initMap">
</script>

這段程式碼的流程可以拆成三個部分:

  1. 從 GeoJSON 取出 Polygon 的座標
  2. [lng, lat] 轉換成 { lat, lng }
  3. 使用 containsLocation() 判斷指定座標是否在 Polygon 內

這樣就能把 geojson.io 繪製出的範圍,轉成實際可用的 Google Maps 地理柵欄。

實際演示結果

實際執行後,Google Maps 會在地圖上顯示從 GeoJSON 轉換而來的多邊形範圍。範例中的藍色半透明區塊就是地理柵欄,代表我們在 geojson.io 中繪製並匯出的 Polygon。

在這個演示中,程式會建立一個測試座標 userLocation,再透過 containsLocation() 判斷它是否落在多邊形內。如果座標位於範圍內,Console 會輸出「位於地理柵欄內」;如果座標落在範圍外,則會輸出「位於地理柵欄外」。

透過這個結果可以確認兩件事:第一,GeoJSON 的座標已經正確轉換成 Google Maps 可使用的 { lat, lng } 格式;第二,地理柵欄不只是畫在地圖上的視覺範圍,也能進一步用來執行位置判斷邏輯。

實務開發時需要注意的細節

在實作地理柵欄時,除了能不能畫出範圍之外,還有幾個細節需要特別注意。

首先是座標順序。GeoJSON 使用 [lng, lat],Google Maps 常用 { lat, lng },這是最容易踩到的問題。只要地圖上的多邊形位置明顯跑掉,第一件事通常就是檢查座標順序是否轉錯。

其次是多邊形是否封閉。GeoJSON 的 Polygon 通常會讓第一個座標與最後一個座標相同,用來表示封閉範圍。使用 geojson.io 繪製時通常會自動處理,但如果後續有手動編輯 JSON,就要確認座標沒有被刪掉。

另外,如果地理柵欄資料會存在後端或資料庫,建議保留原始 GeoJSON 格式。這樣之後不論要顯示在地圖上、提供 API,或是轉換給其他 GIS 工具使用,都會比較彈性。

最後,如果範圍比較複雜,例如包含多個區域或洞口,GeoJSON 可能會出現 MultiPolygon 或 Polygon holes。這類資料在顯示上通常沒有太大問題,但如果要做位置判斷,就需要確認轉換邏輯有完整支援對應結構。

遊戲畫面效果

套用到遊戲情境後,地理柵欄可以轉換成畫面上的區域觸發效果。當玩家目前位置進入指定範圍時,遊戲可以即時改變 UI 狀態,例如顯示「已進入任務區域」、開啟互動按鈕,或觸發特定事件。

以下畫面可以看到,地圖上的地理範圍不只是開發時的輔助標記,也能成為遊戲流程的一部分。玩家移動到範圍內後,系統會依照位置判斷結果更新畫面狀態,讓地圖位置與遊戲互動產生連動。

這種設計很適合用在實境遊戲或活動任務中。例如玩家需要抵達指定地點才能開始挑戰,或是只有在特定區域內才會出現任務提示。透過 GeoJSON 管理區域範圍,再由 Google Maps 負責位置判斷,就能把真實地理空間轉換成遊戲中的互動條件。

小結

使用 geojson.io 建立 Google Maps 地理柵欄,可以讓範圍繪製變得更直覺,也能避免手動輸入大量座標造成的錯誤。整體流程可以整理成以下幾步:

  1. geojson.io 上找到目標區域
  2. 使用 Polygon 工具畫出地理柵欄
  3. 匯出或複製 GeoJSON
  4. 在 Google Maps 中顯示 GeoJSON
  5. 將 GeoJSON 座標轉換成 Google Maps Polygon
  6. 使用 Geometry Library 判斷座標是否位於範圍內

對於需要快速製作地圖互動原型、活動區域判斷或位置觸發功能的專案來說,這是一個簡單又實用的工作流程。只要掌握 GeoJSON 與 Google Maps 座標格式的差異,就能順利把視覺化繪製出的地理範圍轉換成實際可執行的程式邏輯。