Google Maps JavaScript API V3的使用(二)

Google Maps JavaScript API V3 事件


地图事件概述

浏览器中的 JavaScript 是事件驱动的,这表示 JavaScript 通过生成事件来响应交互,并期望程序侦听感兴趣的事件Google Maps API 第 3 版的事件模型与 Google Maps API 第 2 版中所使用的事件模型在内在机制上尽管有很大的不同,但两者是十分相似的。有两种类型的事件:

  • 用户事件(如“点击”鼠标事件)是从 DOM 传播到 Google Maps API 中的。这些事件是独立的,并且与标准 DOM 事件不同。
  • MVC 状态更改通知反映了 Google Maps API 对象中的更改,并以 property_changed 惯例命名

每个 Google Maps API 对象都可导出大量已命名的事件。如果程序想要实现某些事件,则会为这些事件注册 Javascript 事件侦听器,并会在通过在 google.maps.event 命名空间中注册 addListener() 事件处理程序接收这些事件时执行相应的代码。Google Maps API 第 2 版的开发人员应该会熟悉这一用法。

有关事件的完整列表,请参见 Google Maps API 参考。至于包含事件的各个对象,我们在单独的部分中列出了这些对象的事件。

用户界面事件

Google Maps API 中的一些对象旨在对用户事件(例如鼠标事件或键盘事件)作出响应。google.maps.Marker 对象可以侦听以下用户事件,例如:

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

这些事件可能看上去像是标准 DOM 事件,但实际上却是 Google Maps API 的一部分。由于不同的浏览器可实现不同的 DOM 事件模型,因此,Google Maps API 提供了无需处理各种跨浏览器特性便可侦听和响应 DOM 事件的机制。这些事件通常还会在表明某些用户界面状态(例如鼠标位置)的事件中传递参数。

MVC 状态更改

MVC 对象通常都有相应的状态。只要更改了对象的属性,那么,API 就会触发已更改该属性的事件。例如,当地图的缩放级别更改后,API 将会触发地图上的 zoom_changed 事件。您也可以通过在 event 命名空间方法中注册 addListener() 事件处理程序的方式截获这些状态更改。

用户事件和 MVC 状态更改看上去很相似,但通常情况下,您应该在代码中对它们进行不同的处理。例如,MVC 事件不在它们的事件中传递参数。您可能需要通过调用该对象上相应的 getProperty 方法,检查在 MVC 状态更改中更改的属性。

地图事件

您可使用 addListener() 事件处理程序注册以接收事件通知。该方法有三个参数,一个对象,一个待侦听事件以及一个在指定事件发生时调用的函数。

以下代码可将用户事件和状态更改事件进行组合。我们可将事件处理程序附加到点击时对地图执行缩放操作的标记上。我们还针对“zoom”属性的更改在地图中添加了事件处理程序,并在收到 zoom_changed 事件时将地图移动到澳大利亚北领地的达尔文市:

var map;
function initialize() {
  var myLatlng = new google.maps.LatLng(-25.363882,131.044922);
  var myOptions = {
    zoom: 4,
    center: myLatlng,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  }
  map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
  
  google.maps.event.addListener(map, 'zoom_changed', function() {
    setTimeout(moveToDarwin, 3000);
  });
  
  var marker = new google.maps.Marker({
      position: myLatlng, 
      map: map,
      title:"Hello World!"
  });
  google.maps.event.addListener(marker, 'click', function() {
    map.setZoom(8);
  });
}
  
function moveToDarwin() {
  var darwin = new google.maps.LatLng(-12.461334, 130.841904);
  map.setCenter(darwin);
}

查看示例 (event-simple.html)

请注意:如果您要尝试检测视口中的更改,请务必使用特定的 bounds_changed 事件,而不要使用作为其组成部分的 zoom_changed 和 center_changed 事件。由于 Google Maps API 会单独触发后面的两个事件,因此,只有在系统强制性地更改了视口后,getBounds() 才能报告有用的结果。如果您想要在此类事件之后实现 getBounds() 方法,请务必侦听bounds_changed 事件。

访问用户界面事件中的参数

通常情况下,Google Maps API 第 3 版中的用户界面事件会传递事件参数,您可通过事件侦听器访问这些参数,这些参数会注明事件发生时用户界面所处的状态。例如,用户界面'click' 事件通常传递包含 latLng 属性的 MouseEvent,该属性指出了地图上的点击位置。请注意,这是用户界面事件所独有的行为;MVC 状态更改不会在它们的事件中传递参数。

您可以访问事件侦听器中的事件参数,这与访问对象属性的方法一样。以下示例介绍了如何为地图添加事件侦听器,以及如何在用户点击地图时,在所点击的位置处创建一个标记。

var map;
function initialize() {
  var myLatlng = new google.maps.LatLng(-25.363882,131.044922);
  var myOptions = {
    zoom: 4,
    center: myLatlng,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  }
  map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
  
  google.maps.event.addListener(map, 'click', function(event) {
    placeMarker(event.latLng);
  });
}
  
function placeMarker(location) {
  var marker = new google.maps.Marker({
      position: location, 
      map: map
  });

  map.setCenter(location);
}

查看示例 (event-arguments.html)

在事件侦听器中使用闭包

在执行事件侦听器时,通常可取的做法是将私有数据和持久性数据附加到对象中。JavaScript 不支持“私有”实例数据,但它支持允许内部函数访问外部变量的闭包。在事件侦听器访问通常不附加到发生事件的对象的变量时,闭包非常有用。

下例在事件侦听器中使用函数闭包将加密消息分配给一组标记。点击每个标记都可以看到加密消息的一部分,该消息并未包含在标记自身内。

var map;
function initialize() {
  var myLatlng = new google.maps.LatLng(-25.363882,131.044922);
  var myOptions = {
    zoom: 4,
    center: myLatlng,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  }

  map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);

  // Add 5 markers to the map at random locations
  var southWest = new google.maps.LatLng(-31.203405,125.244141);
  var northEast = new google.maps.LatLng(-25.363882,131.044922);
  var bounds = new google.maps.LatLngBounds(southWest,northEast);
  map.fitBounds(bounds);
  var lngSpan = northEast.lng() - southWest.lng();
  var latSpan = northEast.lat() - southWest.lat();
  for (var i = 0; i < 5; i++) {
    var location = new google.maps.LatLng(southWest.lat() + latSpan * Math.random(),
        southWest.lng() + lngSpan * Math.random());
    var marker = new google.maps.Marker({
        position: location, 
        map: map
    });
    var j = i + 1;
    marker.setTitle(j.toString());
    attachSecretMessage(marker, i);
  }
}

// The five markers show a secret message when clicked
// but that message is not within the marker's instance data

function attachSecretMessage(marker, number) {
  var message = ["This","is","the","secret","message"];
  var infowindow = new google.maps.InfoWindow(
      { content: message[number],
        size: new google.maps.Size(50,50)
      });
  google.maps.event.addListener(marker, 'click', function() {
    infowindow.open(map,marker);
  });
}

查看示例 (event-closure.html)

获取和设置事件处理程序中的属性

在系统触发事件时,Google Maps API 事件系统中的任何 MVC 状态更改事件都不会传递参数(用户事件确实会传递参数,这是可以检查到的)。如果您需要检查有关 MVC 状态更改的某一属性,则应当显式的调用该对象上相应的 getProperty() 方法。在此检查过程中,系统会始终检索 MVC 对象的“当前状态”,但这一状态可能不是 MVC 对象在首次触发相应事件时所处的状态。

请注意:在对“特定属性”的状态更改作出响应的事件处理程序中,显式设置一个属性可能会产生不可预期的和/或不必要的行为。例如,设置此类属性将会触发新的事件,而且,如果您总是在此事件处理程序中设置属性,那么,您最终可能会出现无限循环的情况。

在以下示例中,我们会设置一个事件处理程序,使其通过构建显示缩放级别的信息窗口对缩放事件作出响应。我们还会检查地图是否已完全缩小,如果是的话,我们会将地图放大到缩放级别 17。

var map;
function initialize() {
  var myLatlng = new google.maps.LatLng(-25.363882,131.044922);
  var myOptions = {
    zoom: 4,
    center: myLatlng,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  }
  map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
  
  var zoomLevel;
  var infowindow = new google.maps.InfoWindow(
    { content: 'Zoom Level Test',
        size: new google.maps.Size(50,50),
        position: myLatlng
    });
  infowindow.open(map);
    
  google.maps.event.addListener(map, 'zoom_changed', function() {
    zoomLevel = map.getZoom();
    infowindow.setContent("Zoom: " + zoomLevel);
    if (zoomLevel == 0) {
      map.setZoom(10);
    }      
  });
}

查看示例 (event-properties.html)

监听 DOM 事件

Google Maps JavaScript API 事件模型会自行创建并管理自定义事件。然而,浏览器内的 DOM(文档对象模型)也会根据所使用的特定浏览器事件模型自行创建并分派事件。如果您希望捕获并响应这些事件,则可使用 Maps API 提供的 addDomListener() 静态方法来监听并绑定这些 DOM 事件。

该方法易于使用,并且拥有如下所示的签名:

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

其中 instance 可能是浏览器支持的任意 DOM 元素,包括:

  • DOM 的分层组成部分,如 window 或 document.body.myform
  • 指定的元素,如 document.getElementById("foo")

请注意:addDomListener() 只是将指明的事件传递给浏览器,这样系统会按照浏览器的 DOM 事件模型来处理该事件;然而,几乎所有的热门浏览器都至少支持 DOM 级别 2(关于 DOM 级别事件的详情,请参见 Mozilla DOM 级别参考)。

看到这里,您可能已经熟悉了一个 DOM 事件:window.onload 事件,我们已在 <body> 标记内对其进行了处理。我们使用该事件在 HTML 页面完全加载后触发初始的 JavaScript 代码,具体如下:

<script>
  function initialize() {

    // Map initialization

  }
</script>
<body onload="initialize()">
  <div id="map_canvas"></div>
</body>

尽管此处将该事件附加到了 <body> 元素上,但实际上该事件为 window 事件,表明 window 元素下的 DOM 分层已经全部构建并呈现完毕。

将 onload 事件放置在 <body> 标记内虽然易于理解,但会将内容与行为混淆起来。一般来说,较好的做法是将内容代码 (HTML) 与行为代码 (JavaScript) 分隔开来,同时单独提供显示代码 (CSS)。要实现此目的,您可以将自己的 Maps API JavaScript 代码中的内嵌 onload 事件处理程序替换为 DOM 监听器,如下所示:

<script>
  function initialize() {

    // Map initialization

  }
  
  google.maps.event.addDomListener(window, 'load', initialize);
</script>
<body>
  <div id="map_canvas"></div>
</body>

查看示例 (event-domListener.html)

尽管上述代码为 Maps JavaScript API 代码,但 addDomListener() 方法会绑定到浏览器的 window 对象,并允许该 API 与其常规域之外的对象进行通信。

你可能感兴趣的:(Google Maps JavaScript API V3的使用(二))