同樣好用的地圖,再加上 SLA、支援以及廣告的控制
瀏覽器中的 JavaScript 為「事件驅動」,會因應互動事件而再產生事件,並預期程式會「接聽」相關的事件。例如在瀏覽器中,使用者滑鼠和鍵盤的互動就會建立 DOM 中的事件。與特定事件相關的程式,會為那些事件註冊 JavaScript 事件接聽程式,並於接收到那些事件時執行程式碼。
藉由定義「地圖 API」物件的自訂事件,「Google 地圖 API」新增此事件模型。需要注意的是,「地圖 API」事件與標準的 DOM 事件是獨立且不同的。然而,因為不同瀏覽器實作不同的 DOM 事件模型,因此「地圖 API」也提供機制,來接聽或回應這些 DOM 事件,而不需要處理各種跨瀏覽器的細節。
「Google 地圖 API」中的事件,是使用 GEvent 命名空間中公用程式函式註冊事件接聽程式的方式進行處理。每個「地圖 API」物件匯出一系列具名的事件。例如,GMap2 物件匯出 click、dblclick 和 move 事件,其他物件也會產生類似事件。每個事件會在指定情境中發生,而且可以傳送識別該情境的引數。例如,如果使用者在地圖物件中移動滑鼠,並傳送滑鼠所在之地理位置的 GLatLng,就會引發 mousemove 事件。
如需 GMap2 事件及其產生引數的完整清單,請參閱 GMap2.Events。
若要註冊這些事件的通知,請使用靜態方法 GEvent.addListener()。該方法可接受物件、要接聽的事件以及特定事件發生時要呼叫的函式。例如,每當使用者在地圖上按一下,此程式碼片段就會顯示警示:
var map = new GMap2(document.getElementById("map"));
map.setCenter(new GLatLng(37.4419, -122.1419), 13);
GEvent.addListener(map, "click", function() {
alert("You clicked the map.");
});
接聽程式也可以擷取事件的情境。下列範例程式碼中,我們顯示使用者拖曳地圖後該地圖中心的經緯度。
var map = new GMap2(document.getElementById("map"));
GEvent.addListener(map, "moveend", function() {
var center = map.getCenter();
document.getElementById("message").innerHTML = center.toString();
});
map.setCenter(new GLatLng(37.4419, -122.1419), 13);
執行事件接聽程式時,物件最好同時具有私有和持續性資料。JavaScript 不支援「private」實例資料,但是支援 closure (可允許內部函式存取外部變數)。Closure 在事件接聽程式中很有用,可存取一般通常不會附加至事件發生時物件上的變數。
下列範例在事件接聽程式中使用函式 Closure,以指派秘密訊息給標記集。按一下每個標記可檢視秘密訊息的一部分,標記本身不含秘密訊息。
var map = new GMap2(document.getElementById("map_canvas"));
map.setCenter(new GLatLng(37.4419, -122.1419), 13);
// Creates a marker at the given point
// The five markers show a secret message when clicked
// but that message is not within the marker's instance data
function createMarker(point, number) {
var marker = new GMarker(point);
var message = ["This","is","the","secret","message"];
marker.value = number;
GEvent.addListener(marker, "click", function() {
var myHtml = "<b>#" + number + "</b><br/>" + message[number -1];
map.openInfoWindowHtml(point, myHtml);
});
return marker;
}
// Add 5 markers to the map at random locations
var bounds = map.getBounds();
var southWest = bounds.getSouthWest();
var northEast = bounds.getNorthEast();
var lngSpan = northEast.lng() - southWest.lng();
var latSpan = northEast.lat() - southWest.lat();
for (var i = 0; i < 5; i++) {
var point = new GLatLng(southWest.lat() + latSpan * Math.random(),
southWest.lng() + lngSpan * Math.random());
map.addOverlay(createMarker(point, i + 1));
}
「地圖 API」事件系統中的很多事件,在事件觸發時,都會傳送引數。如果在地圖的疊加層發生點擊的話,則 GMap2「按一下」事件會傳送 overlay 和 overlaylatlng;否則它會傳送地圖座標的 latlng。您可以將指定的符號直接傳送給事件接聽程式中的函式,以使用這些引數。
在下列範例中,我們先進行測試,以確認「按一下」是位於地圖方塊上 (檢查是否已定義 latlng 引數);如果是的話,我們會在按一下的座標上方開啟資訊視窗,顯示轉換為像素空間與縮放等級的座標。
var map = new GMap2(document.getElementById("map_canvas"));
map.setCenter(new GLatLng(37.4419, -122.1419), 13);
GEvent.addListener(map,"click", function(overlay, latlng) {
if (latlng) {
var myHtml = "The GPoint value is: " + map.fromLatLngToDivPixel(latlng) + " at zoom level " + map.getZoom();
map.openInfoWindow(latlng, myHtml);
}
});
map.addControl(new GSmallMapControl());
map.addControl(new GMapTypeControl());
如果想要將事件接聽程式附加至物件的特定實例,函式就非常好用。如果相反地,您是希望有方法可以叫用回應事件之物件的所有實例,則可以使用 GEvent.bind()。在下列範例中,應用程式類別實例將地圖事件繫結至其本身的方法中,當事件觸發時會修改類別狀態:
function MyApplication() {
this.counter = 0;
this.map = new GMap2(document.getElementById("map"));
this.map.setCenter(new GLatLng(37.4419, -122.1419), 13);
GEvent.bind(this.map, "click", this, this.onMapClick);
}
MyApplication.prototype.onMapClick = function() {
this.counter++;
alert("You have clicked the map " + this.counter + " " +
(this.counter == 1 ? "time" : "times"));
}
var application = new MyApplication();
「Google 地圖 API」事件模型建立並管理其本身的自訂事件。不過,DOM 也會根據使用中的特殊瀏覽器事件模型,來建立並分派其自己的事件。如果您想要擷取並回應這些事件,「Google 地圖 API」提供適用各種瀏覽器的包裝函式,來接聽和繫結 DOM 事件,而不需要自訂程式碼。
GEvent.addDomListener() 靜態方法會在 DOM 節點為 DOM 事件註冊事件處理常式。同樣地,靜態方法 GEvent.bindDom() 允許您為類別實例上的 DOM 事件註冊事件處理常式。
不再需要事件接聽程式時,應將它移除。如果事件只需要引發一次,就可能需要用到。要移除在 Closure 中透過匿名函式定義的事件接聽程式,可能有點困難。不過,addListener()、addDomListener()、bind() 以及 bindDom() 函式會傳回 GEventListener 控制代碼,可於稍後解除註冊處理常式。
下列範例會在地圖上放置標記,以回應按一下的動作。任何後續的點擊都會移除該事件接聽程式。請注意,removeOverlay() 程式碼不會作為結果執行。同時,也請注意,您甚至可以在事件接聽程式本身之中移除事件接聽程式。
function MyApplication() {
this.counter = 0;
this.map = new GMap2(document.getElementById("map"));
this.map.setCenter(new GLatLng(37.4419, -122.1419), 13);
var myEventListener = GEvent.bind(this.map, "click", this, function(overlay, latlng) {
if (this.counter == 0) {
if (latlng) {
this.map.addOverlay(new GMarker(latlng))
this.counter++;
} else if (overlay instanceof GMarker) {
this.removeOverlay(marker)
}
} else {
GEvent.removeListener(myEventListener);
}
});
}
function load() {
var application = new MyApplication();
}