Sự kiện

Chọn nền tảng: Android iOS JavaScript

Trang này mô tả các sự kiện lỗi và sự kiện trên giao diện người dùng mà bạn có thể theo dõi và xử lý theo phương thức lập trình.

Sự kiện trên giao diện người dùng

JavaScript trong trình duyệt được điều khiển bằng sự kiện, có nghĩa là JavaScript phản hồi các hoạt động tương tác bằng cách tạo các sự kiện và dự kiến một chương trình sẽ lắng nghe các sự kiện thú vị. Có hai loại sự kiện:

  • Các sự kiện của người dùng (chẳng hạn như sự kiện "nhấp chuột") được truyền từ DOM đến API JavaScript của Maps. Những sự kiện này riêng biệt và khác biệt với các sự kiện DOM tiêu chuẩn.
  • Thông báo về thay đổi trạng thái của MVC phản ánh những thay đổi trong đối tượng API JavaScript của Maps và được đặt tên theo quy ước property_changed.

Mỗi đối tượng API JavaScript của Maps xuất một số sự kiện được đặt tên. Những chương trình quan tâm đến một số sự kiện nhất định sẽ đăng ký trình nghe sự kiện JavaScript cho những sự kiện đó và thực thi mã khi nhận được các sự kiện đó bằng cách gọi addListener() để đăng ký trình xử lý sự kiện trên đối tượng.

Mẫu sau đây sẽ cho bạn biết những sự kiện nào được google.maps.Map kích hoạt khi bạn tương tác với bản đồ.

Để biết danh sách đầy đủ các sự kiện, hãy tham khảo Tài liệu tham khảo API JavaScript của Maps. Sự kiện được liệt kê trong một phần riêng cho mỗi đối tượng chứa sự kiện.

Sự kiện giao diện người dùng

Một số đối tượng trong API JavaScript của Maps được thiết kế để phản hồi các sự kiện của người dùng, chẳng hạn như các sự kiện về chuột hoặc bàn phím. Ví dụ: dưới đây là một số sự kiện của người dùng mà đối tượng google.maps.marker.AdvancedMarkerElement có thể theo dõi:

  • 'click'
  • 'drag'
  • 'dragend'
  • 'dragstart'
  • 'gmp-click'

Để xem danh sách đầy đủ, hãy xem lớp AdvancedMarkerElement. Những sự kiện này có thể trông giống như các sự kiện DOM chuẩn, nhưng thực ra là một phần của API JavaScript của Maps. Vì các trình duyệt khác nhau triển khai các mô hình sự kiện DOM khác nhau, nên API JavaScript của Maps cung cấp những cơ chế này để theo dõi và phản hồi các sự kiện DOM mà không cần phải xử lý các đặc điểm khác nhau trên nhiều trình duyệt. Những sự kiện này cũng thường truyền đối số trong sự kiện ghi chú một số trạng thái giao diện người dùng (chẳng hạn như vị trí chuột).

Các thay đổi về trạng thái MVC

Các đối tượng MVC thường chứa trạng thái. Bất cứ khi nào thuộc tính của một đối tượng thay đổi, API JavaScript của Maps sẽ kích hoạt một sự kiện mà thuộc tính đó đã thay đổi. Ví dụ: API sẽ kích hoạt sự kiện zoom_changed trên bản đồ khi mức thu phóng của bản đồ thay đổi. Bạn có thể chặn những thay đổi về trạng thái này bằng cách gọi addListener() để đăng ký các trình xử lý sự kiện trên đối tượng.

Sự kiện của người dùng và thay đổi về trạng thái MVC có thể trông giống nhau, nhưng bạn thường nên xử lý chúng theo cách khác nhau trong mã. Ví dụ: các sự kiện MVC sẽ không truyền đối số trong sự kiện của chúng. Bạn sẽ muốn kiểm tra thuộc tính đã thay đổi khi trạng thái MVC thay đổi bằng cách gọi phương thức getProperty thích hợp trên đối tượng đó.

Xử lý sự kiện

Để đăng ký nhận thông báo sự kiện, hãy sử dụng trình xử lý sự kiện addListener(). Phương thức đó sẽ nhận một sự kiện để theo dõi và một hàm để gọi khi sự kiện đã chỉ định xảy ra.

Ví dụ: Sự kiện trên bản đồ và điểm đánh dấu

Mã sau đây kết hợp sự kiện của người dùng với sự kiện thay đổi trạng thái. Chúng tôi đính kèm trình xử lý sự kiện vào một điểm đánh dấu để thu phóng bản đồ khi người dùng nhấp vào. Chúng tôi cũng thêm một trình xử lý sự kiện vào bản đồ cho các thay đổi đối với thuộc tính center và xoay bản đồ về điểm đánh dấu sau 3 giây kể từ khi nhận được sự kiện center_changed:

TypeScript

async function initMap() {
  // Request needed libraries.
  const { Map } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary;
  const { AdvancedMarkerElement } = await google.maps.importLibrary("marker") as google.maps.MarkerLibrary;

  const myLatlng = { lat: -25.363, lng: 131.044 };

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

  const marker = new google.maps.marker.AdvancedMarkerElement({
    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.position as google.maps.LatLng);
    }, 3000);
  });

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

initMap();

JavaScript

async function initMap() {
  // Request needed libraries.
  const { Map } = await google.maps.importLibrary("maps");
  const { AdvancedMarkerElement } = await google.maps.importLibrary("marker");
  const myLatlng = { lat: -25.363, lng: 131.044 };
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 4,
    center: myLatlng,
    mapId: "DEMO_MAP_ID",
  });
  const marker = new google.maps.marker.AdvancedMarkerElement({
    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.position);
    }, 3000);
  });
  marker.addListener("click", () => {
    map.setZoom(8);
    map.setCenter(marker.position);
  });
}

initMap();
Xem ví dụ

Thử dùng mẫu

Mẹo: Nếu bạn đang cố gắng phát hiện một thay đổi trong khung nhìn, hãy nhớ sử dụng sự kiện bounds_changed cụ thể thay vì các sự kiện zoom_changedcenter_changed cấu thành. Vì API JavaScript của Maps kích hoạt các sự kiện sau một cách độc lập, nên getBounds() có thể không báo cáo kết quả hữu ích cho đến khi khung nhìn đã được thay đổi một cách có căn cứ. Nếu bạn muốn getBounds() sau một sự kiện như vậy, hãy nhớ theo dõi sự kiện bounds_changed.

Ví dụ: Sự kiện chỉnh sửa hình dạng và kéo

Khi bạn chỉnh sửa hoặc kéo một hình dạng, một sự kiện sẽ được kích hoạt sau khi hoàn tất thao tác. Để biết danh sách các sự kiện và một số đoạn mã, hãy xem phần Hình dạng.

Xem ví dụ (rectangle-event.html)

Truy cập đối số trong các sự kiện trên giao diện người dùng

Các sự kiện giao diện người dùng trong API JavaScript của Maps thường truyền một đối số sự kiện mà trình nghe sự kiện có thể truy cập, ghi nhận trạng thái giao diện người dùng khi sự kiện đó xảy ra. Ví dụ: sự kiện 'click' trên giao diện người dùng thường truyền một MouseEvent chứa thuộc tính latLng cho biết vị trí được nhấp vào trên bản đồ. Xin lưu ý rằng hành vi này chỉ dành cho các sự kiện giao diện người dùng; các thay đổi về trạng thái MVC sẽ không truyền đối số vào các sự kiện tương ứng.

Bạn có thể truy cập các đối số của sự kiện trong trình nghe sự kiện giống như cách bạn truy cập vào các thuộc tính của một đối tượng. Ví dụ sau đây thêm một trình nghe sự kiện cho bản đồ và tạo một điểm đánh dấu khi người dùng nhấp vào bản đồ tại vị trí đã nhấp vào.

TypeScript

async function initMap() {
  // Request needed libraries.
  const { Map } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary;
  const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary("marker") as google.maps.MarkerLibrary;

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

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

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

initMap();

JavaScript

async function initMap() {
  // Request needed libraries.
  const { Map } = await google.maps.importLibrary("maps");
  const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary(
    "marker",
  );
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 4,
    center: { lat: -25.363882, lng: 131.044922 },
    mapId: "DEMO_MAP_ID",
  });

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

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

initMap();
Xem ví dụ

Thử dùng mẫu

Sử dụng quy tắc đóng trong Trình nghe sự kiện

Khi thực thi trình nghe sự kiện, bạn nên đính kèm cả dữ liệu riêng tư và cố định vào một đối tượng. JavaScript không hỗ trợ dữ liệu thực thể "riêng tư", nhưng có hỗ trợ trạng thái đóng cho phép các hàm bên trong truy cập vào các biến bên ngoài. Việc đóng rất hữu ích trong trình nghe sự kiện để truy cập vào các biến thường không được đính kèm vào đối tượng xảy ra sự kiện.

Ví dụ sau đây sử dụng hàm đóng trong trình nghe sự kiện để gán thông báo bí mật cho một tập hợp các điểm đánh dấu. Khi nhấp vào mỗi điểm đánh dấu, bạn sẽ thấy một phần của thông báo bí mật không có trong chính điểm đánh dấu.

TypeScript

async function initMap() {
  // Request needed libraries.
  const { Map } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary;
  const { AdvancedMarkerElement } = await google.maps.importLibrary("marker") as google.maps.MarkerLibrary;

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

  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.AdvancedMarkerElement({
      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.AdvancedMarkerElement,
  secretMessage: string
) {
  const infowindow = new google.maps.InfoWindow({
    content: secretMessage,
  });

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

initMap();

JavaScript

async function initMap() {
  // Request needed libraries.
  const { Map } = await google.maps.importLibrary("maps");
  const { AdvancedMarkerElement } = await google.maps.importLibrary("marker");
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 4,
    center: { lat: -25.363882, lng: 131.044922 },
    mapId: "DEMO_MAP_ID",
  });
  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.AdvancedMarkerElement({
      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.map, marker);
  });
}

initMap();
Xem ví dụ

Thử dùng mẫu

Nhận và đặt thuộc tính trong Trình xử lý sự kiện

Không có sự kiện thay đổi trạng thái MVC nào trong hệ thống sự kiện API JavaScript của Maps truyền đối số khi sự kiện được kích hoạt. (Sự kiện người dùng sẽ truyền các đối số có thể kiểm tra được.) Nếu cần kiểm tra một thuộc tính khi trạng thái MVC thay đổi, bạn nên gọi phương thức getProperty() thích hợp trên đối tượng đó một cách rõ ràng. Yêu cầu kiểm tra này sẽ luôn truy xuất trạng thái hiện tại của đối tượng MVC (có thể không phải là trạng thái khi sự kiện được kích hoạt lần đầu tiên).

Lưu ý: Việc đặt rõ ràng một thuộc tính trong một trình xử lý sự kiện để phản hồi thay đổi trạng thái của thuộc tính đó có thể gây ra hành vi ngoài dự đoán và/hoặc không mong muốn. Ví dụ: việc đặt một thuộc tính như vậy sẽ kích hoạt một sự kiện mới. Nếu luôn thiết lập một thuộc tính trong trình xử lý sự kiện này, thì có thể bạn sẽ tạo một vòng lặp vô hạn.

Trong ví dụ dưới đây, chúng ta thiết lập một trình xử lý sự kiện để phản hồi các sự kiện thu phóng bằng cách hiển thị một cửa sổ thông tin hiển thị cấp độ đó.

TypeScript

async function initMap() {
  // Request needed libraries.
  const { Map } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary;

  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()!);
  });
}

initMap();

JavaScript

async function initMap() {
  // Request needed libraries.
  const { Map } = await google.maps.importLibrary("maps");
  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());
  });
}

initMap();
Xem ví dụ

Thử dùng mẫu

Nghe sự kiện DOM

Mô hình sự kiện API JavaScript của Maps sẽ tạo và quản lý các sự kiện tuỳ chỉnh của riêng nó. Tuy nhiên, DOM (Mô hình đối tượng tài liệu) trong trình duyệt cũng tạo và gửi các sự kiện của chính nó, tuỳ theo mô hình sự kiện trình duyệt cụ thể đang được sử dụng. Nếu bạn muốn thu thập và phản hồi những sự kiện này, thì API JavaScript của Maps sẽ cung cấp phương thức tĩnh addDomListener() để theo dõi và liên kết với các sự kiện DOM.

Phương thức tiện lợi này có chữ ký như sau:

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

trong đó instance có thể là bất kỳ phần tử DOM nào được trình duyệt hỗ trợ, bao gồm:

  • Các thành phần phân cấp của DOM như window hoặc document.body.myform
  • Các phần tử được đặt tên, chẳng hạn như document.getElementById("foo")

Lưu ý rằng addDomListener() chuyển sự kiện được chỉ định đến trình duyệt, trình duyệt này sẽ xử lý sự kiện đó theo mô hình sự kiện DOM của trình duyệt. Tuy nhiên, hầu hết các trình duyệt hiện đại đều ít nhất hỗ trợ DOM cấp 2. (Để biết thêm thông tin về các sự kiện ở cấp DOM, hãy xem tài liệu tham khảo về Các cấp độ DOM của Mozilla.)

TypeScript

async function initMap() {
  // Request needed libraries.
  const { Map } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary;

  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!");
  });
}

initMap();

JavaScript

async function initMap() {
  // Request needed libraries.
  const { Map } = await google.maps.importLibrary("maps");
  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!");
  });
}

initMap();

HTML

<html>
  <head>
    <title>Listening to DOM Events</title>

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

    <!-- prettier-ignore -->
    <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})
        ({key: "AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg", v: "weekly"});</script>
  </body>
</html>
Xem ví dụ

Thử dùng mẫu

Mặc dù mã ở trên là mã API Maps JavaScript, nhưng phương thức addDomListener() liên kết với đối tượng window của trình duyệt và cho phép API giao tiếp với các đối tượng bên ngoài miền thông thường của API.

Xoá trình nghe sự kiện

Để xoá một trình nghe sự kiện cụ thể, bạn phải chỉ định trình nghe sự kiện đó cho một biến. Sau đó, bạn có thể gọi removeListener(), truyền tên biến được chỉ định trình nghe.

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

google.maps.event.removeListener(listener1);

Để xoá tất cả trình nghe khỏi một thực thể cụ thể, hãy gọi clearInstanceListeners(), truyền tên thực thể.

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

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

Để xoá tất cả trình nghe cho một loại sự kiện cụ thể của một thực thể cụ thể, hãy gọi clearListeners(), truyền tên thực thể và tên sự kiện.

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');

Để biết thêm thông tin, hãy tham khảo tài liệu tham khảo về không gian tên google.maps.event.

Nghe lỗi xác thực

Nếu muốn phát hiện lỗi xác thực bằng cách lập trình (ví dụ: tự động gửi beacon), bạn có thể chuẩn bị một hàm gọi lại. Nếu bạn xác định hàm chung sau đây, thì hàm này sẽ được gọi khi quá trình xác thực không thành công. function gm_authFailure() { /* Code */ };