Google Maps API v3 實用技巧 (四) References to Objects

其 實 嚴 格 黎 講 ,本 文 的 內 容 應 該 係 一 篇 Javascript 的 基 礎 ,而 唔 係 好 關 Google Maps API 的 事 。

Okay,廢 話 少 說 。我 們 簡 單 的 回 顧 一 下 ,什 麼 是 Javascript Objects 呢 ?無 限 簡 化 到 有 點 偏 頗 地 講 ,Objects 就 好 似 Variables,但 Object 儲 存 既 唔 係 單 單 一 個 value,而 係 可 以 儲 存 好 多 好 多 個 values ( 叫 properties )。除 了 values 之 外 ,objects 仲 可 以 儲 存 好 多 好 多 條 funtions ( 叫 methods )。

Javascript Objects 同 Google Map API 有 咩 關 係 呢 ?Well,簡 單 的 來 說 ,Google Map API 裡 面 所 有 的 東 西 都 是 Javascript Objects。不 管 是 那 map 本 身 ,還 是 maker、polyline、inforwindow 等 等 等 等 ,通 通 都 是 Javascript Objects。

要 使 用 Javascript Objects 很 簡 單 ,一 般 我 們 會 使 用 object 本 身 的 constructor。

1
2
3
4
5
6
7
8
...
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
...
var marker = new google.maps.Marker({
   position: new google.maps.LatLng(22.40,114.34),
   map: map,
});
...

在 每 次 create new object 的 時 間 ,我 們 都 會 給 它 一 個 名 字 。例 如 在 上 例 中 ,google map 就 叫 做 map,google map marker 就 叫 maker。那 一 個 名 字 ,更 正 確 的 講 法 應 該 係 那 個 剛 剛 create 出 來 的 object 的 reference。這 個 reference 的 用 處 是 ,我 們 以 後 想 再 對 之 前 create 出 來 的 object 有 所 動 作 ,就 可 以 利 用 它 。

以 上 都 是 老 生 常 談 吧 ?哈 哈 哈 ,大 家 就 當 是 溫 故 知 新 好 了 。

讀 者 Tommy 想 要 在 第 二 個 infowindow 開 啟 的 時 候 ,自 動 關 關 第 一 個 已 經 打 開 了 的 infowindow,說 「試 了 很 多 網 路 上 的 方 法 都 失 敗 了 」。我 想 Tommy 遇 到 的 問 題 ,不 是 他 不 會 使 用 infowindow.close() 方 法 ,而 是 他 不 知 道 第 一 個 已 經 打 開 了 的 infowindow 的 reference。

Object 的 reference,其 實 就 和 variable 一 樣 ,都 有 scope 的 ( global vs local )。如 果 你 希 望 所 有 function 都 能 夠 使 用 這 個 reference,就 記 得 要 把 它 設 置 成 global scope。不 過 同 一 張 google map 可 能 會 有 很 多 很 多 很 多 很 多 很 多 很 多 objects 的 ( 例 如 我 寫 的 行 山 地 圖 ,一 條 行 山 路 線 的 polyline 閒 閒 地 會 有 幾 千 個 點 ),所 以 寫 程 式 之 前 要 考 慮 清 楚 ,真 的 不 是 所 有 object 都 有 需 要 設 置 成 global 的 。

1
2
3
4
...
var marker1 = new google.maps.Marker({...});
var marker2 = new google.maps.Marker({...});
...

當 一 張 地 圖 有 很 多 objects 的 時 候 ,如 何 命 名 和 管 理 也 會 成 為 一 個 難 題 。如 果 你 還 記 得 《Google Maps API v3 實 用 技 巧 (二 ) Markers》的 內 容 ,我 是 用 Array 來 儲 存 同 類 的 objects 的 。

1
2
3
4
5
6
7
8
...
var Markers = [];
...
function addMarker(map, location, title, content) {
   var marker = new google.maps.Marker({...});
   Markers.push(marker);
}
...

大 家 要 留 意 的 是 ,這 些 maker 的 reference,唔 係 理 所 當 然 會 永 遠 存 在 的 ,而 係 要 靠 你 自 己 用 程 式 碼 去 記 錄 低 ,留 待 以 後 用 的 。

1
2
3
4
5
6
7
8
...
// var Markers = [];
...
function addMarker(map, location, title, content) {
   var marker = new google.maps.Marker({...});
   // Markers.push(marker);
}
...

如 果 換 成 上 面 的 這 一 種 寫 法 ,Google map 上 面 看 起 來 是 不 會 有 分 別 的 ,maker 依 然 會 正 確 地 新 增 到 google map。但 那 個 maker 的 reference 在 function 完 結 時 就 永 遠 消 失 了 ,你 以 後 也 不 能 再 對 那 些 maker 做 些 什 麼 了 ( 因 為 上 例 的 maker 只 是 lacal 的 )。

明 白 了 這 個 道 理 ,我 們 再 回 去 看 看 我 在 《Google Maps API v3 實 用 技 巧 (二 ) Markers》的 例 子 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
var Markers = [];
...
function addMarker(map, location, title, content) {
   var marker = new google.maps.Marker({...});
   ...
   var infowindow = new google.maps.InfoWindow({...});
   ...
   google.maps.event.addListener(marker, 'click', function() {
      infowindow.open(map, marker);
   });
   Markers.push(marker);
}
...

很 明 顯 的 ,上 例 之 中 ,我 完 全 沒 有 把 infowindow 的 reference 儲 存 下 來 ,所 以 你 當 然 就 唔 可 能 之 後 再 去 對 它 們 做 些 什 麼 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...
var Markers = [];
var Infowindows = [];
...
function addMarker(map, location, title, content) {
   var marker = new google.maps.Marker({...});
   ...
   var infowindow = new google.maps.InfoWindow({...});
   ...
   google.maps.event.addListener(marker, 'click', function() {
      infowindow.open(map, marker);
   });
   Markers.push(marker);
   Infowindows.push(infowindow);
}
...

其 中 一 種 做 法 ,就 是 增 加 一 個 新 的 global array,Infowindows。然 後 把 所 有 infowindows 的 references 都 儲 存 在 裡 面 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
var Markers = [];
...
function addMarker(map, location, title, content) {
   var marker = new google.maps.Marker({...});
   ...
   marker.infowindow = new google.maps.InfoWindow({...});
   ...
   google.maps.event.addListener(marker, 'click', function() {
      marker.infowindow.open(map, marker);
   });
   Markers.push(marker);
}
...

另 一 種 我 自 己 比 較 prefer,簡 潔 一 點 的 做 法 ,就 是 把 infowindow 的 reference 都 儲 存 在 maker 裡 面 。這 種 寫 法 就 像 是 給 maker object 增 加 了 一 個 property。

1
2
3
...
Markers[0].infowindow.close();
...

以 後 要 refer 返 佢 ,就 可 以 直 接 用 Markers[i].infowindow。

至 於 Tommy 原 本 問 的 問 題 ,如 何 自 動 關 閉 第 一 個 infowindow,最 簡 單 的 可 以 這 樣 做 :

1
2
3
4
5
6
7
8
9
...
var Markers = [];
...
function closeAllInfowindows() {
   for (var i = 0; i < Markers.length; i++) {
      Markers[i].infowindow.close();
   }
}
...

先 寫 一 條 關 閉 所 有 infowindows 的 function,closeAllInfowindows()。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
var Markers = [];
...
function addMarker(map, location, title, content) {
   var marker = new google.maps.Marker({...});
   ...
   marker.infowindow = new google.maps.InfoWindow({...});
   ...
   google.maps.event.addListener(marker, 'click', function() {
      closeAllInfowindows();
      marker.infowindow.open(map, marker);
   });
   Markers.push(marker);
}
...

然 後 再 把 closeAllInfowindows() 加 入 maker 的 click event 裡 面 ( 就 是 先 close all 然 後 再 打 開 要 打 開 的 那 一 個 )。

當 然 ,如 果 你 唔 喜 歡 使 用 這 種 毫 無 美 感 ,非 常 brute force 的 寫 法 ( 別 擔 心 ,我 也 不 喜 歡 ),你 就 要 自 己 再 加 個 flag 去 儲 存 每 一 個 infowindow 的 打 開 狀 態 了 ( infowindow 本 身 的 properties 是 沒 有 這 個 的 )。

有 了 infowindow 的 reference,咁 當 然 唔 止 可 以 用 來 關 閉 infowindow 啦 。infowindow 的 methods 還 有 setContent、SetOptions、SetPosition 等 等 ,可 以 用 來 改 變 infowindow 的 內 容 、外 觀 、位 置 等 等 。

ctleung張先生,男性,肖龍。
職業:I.T. Consultant
簡介:不好好讀書;七尺差五寸,手長過膝,雙耳垂肩;性寬和,寡言語,喜怒不形於色。據說少時曾斬白蛇於鳳凰山下……

This entry was posted in Computer & Network and tagged , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *