活動

選取平台: Android iOS JavaScript

此頁面說明可透過程式監聽及處理的使用者介面事件和錯誤事件。

使用者介面事件

瀏覽器中的 JavaScript 採用事件驅動,也就是說,JavaScript 會透過產生事件來回應互動,並預期程式會「監聽」有趣的事件。事件分為兩種:

  • 使用者事件 (例如「點擊」滑鼠事件) 會從 DOM 傳播至 Maps JavaScript API。這些事件與標準 DOM 事件是獨立且不同的。
  • MVC 狀態變更通知會反映 Maps JavaScript API 物件的變更,並採用 property_changed 慣例命名。

每個 Maps JavaScript API 物件都會匯出多個已命名事件。發生特定事件的程式會註冊這些事件的 JavaScript 事件監聽器,並在呼叫 addListener() 時在物件上註冊事件處理常式,以執行程式碼。

下列範例說明您與地圖互動時,google.maps.Map 觸發的事件。

如需完整的事件清單,請參閱 Maps JavaScript API 參考資料。系統會針對事件所屬的物件,分別在各部分中列出事件。

使用者介面事件

Maps JavaScript API 中的部分物件旨在回應使用者事件,例如滑鼠或鍵盤事件。舉例來說,google.maps.Marker 物件可監聽下列幾種使用者事件:

  • 'click'
  • 'dblclick'
  • 'mouseup'
  • 'mousedown'
  • 'mouseover'
  • 'mouseout'

如需完整清單,請參閱標記類別。這些事件看起來可能與標準 DOM 事件相似,但其實際上是 Maps JavaScript API 的一部分。由於不同的瀏覽器會導入不同的 DOM 事件模型,因此 Maps JavaScript API 提供用於監聽及回應 DOM 事件的機制,不需要處理不同的跨瀏覽器特性。這些事件通常也會在事件中傳送引數,註明部分 UI 狀態 (例如滑鼠位置)。

MVC 狀態變更

MVC 物件通常會包含狀態。只要物件的屬性發生變更,Maps JavaScript API 就會觸發屬性變更的事件。舉例來說,當地圖的縮放等級變更時,API 會在地圖上觸發 zoom_changed 事件。如要攔截狀態變更,請呼叫 addListener() 以在物件上註冊事件處理常式。

使用者事件和 MVC 狀態變更可能相似,但一般而言,請在程式碼中以不同方式處理。舉例來說,MVC 事件並不會在事件中傳送引數。建議您在對該物件呼叫適當的 getProperty 方法,藉此檢查 MVC 狀態變更發生的屬性。

處理事件

如要註冊事件通知,請使用 addListener() 事件處理常式。此方法需要監聽事件,並在指定事件發生時呼叫函式。

範例:地圖與標記事件

下方程式碼會混合使用者事件與狀態變更事件。我們會附加事件處理常式至標記,以便在使用者點選時縮放地圖。此外,我們也為 center 屬性的變更新增地圖事件處理常式,並在收到 center_changed 事件 3 秒後將地圖平移回標記:

TypeScript

function initMap(): void {
  const myLatlng = { lat: -25.363, lng: 131.044 };

  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      zoom: 4,
      center: myLatlng,
    }
  );

  const marker = new google.maps.Marker({
    position: myLatlng,
    map,
    title: "Click to zoom",
  });

  map.addListener("center_changed", () => {
    // 3 seconds after the center of the map has changed, pan back to the
    // marker.
    window.setTimeout(() => {
      map.panTo(marker.getPosition() as google.maps.LatLng);
    }, 3000);
  });

  marker.addListener("click", () => {
    map.setZoom(8);
    map.setCenter(marker.getPosition() as google.maps.LatLng);
  });
}

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;

JavaScript

function initMap() {
  const myLatlng = { lat: -25.363, lng: 131.044 };
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 4,
    center: myLatlng,
  });
  const marker = new google.maps.Marker({
    position: myLatlng,
    map,
    title: "Click to zoom",
  });

  map.addListener("center_changed", () => {
    // 3 seconds after the center of the map has changed, pan back to the
    // marker.
    window.setTimeout(() => {
      map.panTo(marker.getPosition());
    }, 3000);
  });
  marker.addListener("click", () => {
    map.setZoom(8);
    map.setCenter(marker.getPosition());
  });
}

window.initMap = initMap;
查看範例

查看範例

提示:如要嘗試偵測可視區域的變更,請務必使用特定的 bounds_changed 事件,而非組件 zoom_changedcenter_changed 事件。由於 Maps JavaScript API 會獨立觸發後兩者的事件,因此 getBounds() 必須在可視區域已授權變更之後才會回報實用的結果。如果您想在這類事件後想要 getBounds(),請務必監聽 bounds_changed 事件。

範例:形狀編輯及拖曳事件

形狀經過編輯或拖曳時,會在操作完成後觸發事件。如需事件清單和部分程式碼片段,請參閱形狀

查看範例 (rectangle-event.html)

在使用者介面事件中存取引數

Maps JavaScript API 中的 UI 事件通常會傳送事件引數,而事件監聽器可以存取該事件,並記下事件發生時的 UI 狀態。舉例來說,UI 'click' 事件通常會傳送包含 latLng 屬性的 MouseEvent,指出地圖上的點擊位置。請注意,這個行為在 UI 事件中是獨一無二的,MVC 狀態變更不會在事件中傳遞引數。

在事件監聽器中存取事件引數的方式與存取物件屬性的方式相同。以下範例會新增地圖事件監聽器,並在使用者點擊地圖點擊地圖時建立標記。

TypeScript

function initMap(): void {
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      zoom: 4,
      center: { lat: -25.363882, lng: 131.044922 },
    }
  );

  map.addListener("click", (e) => {
    placeMarkerAndPanTo(e.latLng, map);
  });
}

function placeMarkerAndPanTo(latLng: google.maps.LatLng, map: google.maps.Map) {
  new google.maps.Marker({
    position: latLng,
    map: map,
  });
  map.panTo(latLng);
}

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;

JavaScript

function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 4,
    center: { lat: -25.363882, lng: 131.044922 },
  });

  map.addListener("click", (e) => {
    placeMarkerAndPanTo(e.latLng, map);
  });
}

function placeMarkerAndPanTo(latLng, map) {
  new google.maps.Marker({
    position: latLng,
    map: map,
  });
  map.panTo(latLng);
}

window.initMap = initMap;
查看範例

查看範例

在事件監聽器中使用 Closure

執行事件監聽器時,將物件和永久資料附加至物件通常相當實用。JavaScript 不支援「private」執行個體執行個體資料,但支援封閉式,讓內部函式可以存取外部變數。封閉事件在事件監聽器中非常實用,可存取通常附加至發生事件物件的物件。

以下範例使用事件監聽器中的函式封閉功能,將密鑰訊息指派給一組標記。按一下各個標記,即可查看秘密訊息的一部分,但不包含標記本身。

TypeScript

function initMap(): void {
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      zoom: 4,
      center: { lat: -25.363882, lng: 131.044922 },
    }
  );

  const bounds: google.maps.LatLngBoundsLiteral = {
    north: -25.363882,
    south: -31.203405,
    east: 131.044922,
    west: 125.244141,
  };

  // Display the area between the location southWest and northEast.
  map.fitBounds(bounds);

  // Add 5 markers to map at random locations.
  // For each of these markers, give them a title with their index, and when
  // they are clicked they should open an infowindow with text from a secret
  // message.
  const secretMessages = ["This", "is", "the", "secret", "message"];
  const lngSpan = bounds.east - bounds.west;
  const latSpan = bounds.north - bounds.south;

  for (let i = 0; i < secretMessages.length; ++i) {
    const marker = new google.maps.Marker({
      position: {
        lat: bounds.south + latSpan * Math.random(),
        lng: bounds.west + lngSpan * Math.random(),
      },
      map: map,
    });

    attachSecretMessage(marker, secretMessages[i]);
  }
}

// Attaches an info window to a marker with the provided message. When the
// marker is clicked, the info window will open with the secret message.
function attachSecretMessage(
  marker: google.maps.Marker,
  secretMessage: string
) {
  const infowindow = new google.maps.InfoWindow({
    content: secretMessage,
  });

  marker.addListener("click", () => {
    infowindow.open(marker.get("map"), marker);
  });
}

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;

JavaScript

function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 4,
    center: { lat: -25.363882, lng: 131.044922 },
  });
  const bounds = {
    north: -25.363882,
    south: -31.203405,
    east: 131.044922,
    west: 125.244141,
  };

  // Display the area between the location southWest and northEast.
  map.fitBounds(bounds);

  // Add 5 markers to map at random locations.
  // For each of these markers, give them a title with their index, and when
  // they are clicked they should open an infowindow with text from a secret
  // message.
  const secretMessages = ["This", "is", "the", "secret", "message"];
  const lngSpan = bounds.east - bounds.west;
  const latSpan = bounds.north - bounds.south;

  for (let i = 0; i < secretMessages.length; ++i) {
    const marker = new google.maps.Marker({
      position: {
        lat: bounds.south + latSpan * Math.random(),
        lng: bounds.west + lngSpan * Math.random(),
      },
      map: map,
    });

    attachSecretMessage(marker, secretMessages[i]);
  }
}

// Attaches an info window to a marker with the provided message. When the
// marker is clicked, the info window will open with the secret message.
function attachSecretMessage(marker, secretMessage) {
  const infowindow = new google.maps.InfoWindow({
    content: secretMessage,
  });

  marker.addListener("click", () => {
    infowindow.open(marker.get("map"), marker);
  });
}

window.initMap = initMap;
查看範例

查看範例

取得及設定事件處理常式中的屬性

Maps API API 事件系統中的 MVC 狀態變更事件都無法在觸發事件時傳送引數。(使用者事件會傳遞可檢查的引數)。如果您需要檢查 MVC 狀態變更的屬性,您必須在該物件上明確呼叫適當的 getProperty() 方法。這項檢查一律會擷取 MVC 物件的「目前狀態」,但這可能不是事件第一次啟動時的狀態。

注意:在事件處理常式中明確設定屬性,以回應特定屬性的狀態變更時,可能會產生無法預測和/或不必要的行為。舉例來說,設定這類屬性會觸發新事件,而如果您一律在這個事件處理常式中設定屬性,最後可能會產生無限迴圈。

在以下範例中,我們會設定顯示該級別的資訊視窗,以回應縮放事件。

TypeScript

function initMap(): void {
  const originalMapCenter = new google.maps.LatLng(-25.363882, 131.044922);
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      zoom: 4,
      center: originalMapCenter,
    }
  );

  const infowindow = new google.maps.InfoWindow({
    content: "Change the zoom level",
    position: originalMapCenter,
  });

  infowindow.open(map);

  map.addListener("zoom_changed", () => {
    infowindow.setContent("Zoom: " + map.getZoom()!);
  });
}

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;

JavaScript

function initMap() {
  const originalMapCenter = new google.maps.LatLng(-25.363882, 131.044922);
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 4,
    center: originalMapCenter,
  });
  const infowindow = new google.maps.InfoWindow({
    content: "Change the zoom level",
    position: originalMapCenter,
  });

  infowindow.open(map);
  map.addListener("zoom_changed", () => {
    infowindow.setContent("Zoom: " + map.getZoom());
  });
}

window.initMap = initMap;
查看範例

查看範例

監聽 DOM 事件

Maps JavaScript API 事件模型會建立並管理自己的自訂事件。而瀏覽器中的 DOM (文件物件模型) 也會根據使用的特定瀏覽器事件模型,建立及調度本身的事件。如果您想要擷取並回應這些事件,Maps JavaScript API 會提供 addDomListener() 靜態方法來監聽及繫結至 DOM 事件。

這個方法十分簡單,具有以下特徵:

addDomListener(instance:Object, eventName:string, handler:Function)

其中 instance 可以是瀏覽器支援的任何 DOM 元素,包括:

  • 像是 windowdocument.body.myform 的 DOM 階層成員
  • 已命名元素,例如 document.getElementById("foo")

請注意,addDomListener() 會將指定的事件傳送到瀏覽器,並依照瀏覽器的 DOM 事件模型進行處理。不過,幾乎所有新式瀏覽器至少支援 DOM 級別 2。(如要進一步瞭解 DOM 層級事件,請參閱 Mozilla DOM 級別參考資料)。

TypeScript

function initMap(): void {
  const mapDiv = document.getElementById("map") as HTMLElement;
  const map = new google.maps.Map(mapDiv, {
    zoom: 8,
    center: new google.maps.LatLng(-34.397, 150.644),
  });

  // We add a DOM event here to show an alert if the DIV containing the
  // map is clicked.
  google.maps.event.addDomListener(mapDiv, "click", () => {
    window.alert("Map was clicked!");
  });
}

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;

JavaScript

function initMap() {
  const mapDiv = document.getElementById("map");
  const map = new google.maps.Map(mapDiv, {
    zoom: 8,
    center: new google.maps.LatLng(-34.397, 150.644),
  });

  // We add a DOM event here to show an alert if the DIV containing the
  // map is clicked.
  google.maps.event.addDomListener(mapDiv, "click", () => {
    window.alert("Map was clicked!");
  });
}

window.initMap = initMap;

HTML

<html>
  <head>
    <title>Listening to DOM Events</title>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="map"></div>

    <!-- 
     The `defer` attribute causes the callback to execute after the full HTML
     document has been parsed. For non-blocking uses, avoiding race conditions,
     and consistent behavior across browsers, consider loading using Promises
     with https://www.npmjs.com/package/@googlemaps/js-api-loader.
    -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly"
      defer
    ></script>
  </body>
</html>
查看範例

查看範例

雖然上述程式碼是 Maps JavaScript API 程式碼,addDomListener() 方法會繫結至瀏覽器的 window 物件,並允許 API 與 API 一般網域外的物件進行通訊。

移除事件接聽程式

如要移除特定事件監聽器,必須將其指派給變數。接著,您可以呼叫 removeListener(),將已指派給事件監聽器的變數名稱傳遞。

var listener1 = marker.addListener('click', aFunction);

google.maps.event.removeListener(listener1);

如要從特定執行個體中移除所有事件監聽器,請呼叫 clearInstanceListeners() 並傳遞執行個體名稱。

var listener1 = marker.addListener('click', aFunction);
var listener2 = marker.addListener('mouseover', bFunction);

// Remove listener1 and listener2 from marker instance.
google.maps.event.clearInstanceListeners(marker);

如要移除特定執行個體中特定事件類型的所有事件監聽器,請呼叫 clearListeners(),並傳送執行個體名稱和事件名稱。

marker.addListener('click', aFunction);
marker.addListener('click', bFunction);
marker.addListener('click', cFunction);

// Remove all click listeners from marker instance.
google.maps.event.clearListeners(marker, 'click');

詳情請參閱 google.maps.event 命名空間的參考說明文件。

監聽驗證錯誤

如要透過程式偵測驗證失敗情形 (例如自動傳送信標),請準備好回呼函式。如果定義了下列全域函式,當驗證失敗時,系統就會呼叫該函式。function gm_authFailure() { /* Code */ };