GoogleMap在js中的应用
<html> <head> <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=set_to_true_or_false"></script> <script type="text/javascript"> function initialize() { var latlng = new google.maps.LatLng(-34.397, 150.644); var myOptions = { zoom: 8, center: latlng, mapTypeId: google.maps.MapTypeId.ROADMAP }; var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); } </script> </head> <body onload="initialize()"> <div id="map_canvas" style="width:100%; height:100%"></div> </body> </html>
1. 使用 script 标记来加入 Maps API JavaScript。 2. 我们创建一个名为“map_canvas”的 div 元素来承载该地图。 3. 创建 Javascript 对象常量以保存若干地图属性。 4. 编写 Javascript 函数以创建“map”对象。 5. 我们从 body 标记的 onload 事件初始化该地图对象。
载入 Google Maps API <html> <head> <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=set_to_true_or_false"></script> http://maps.google.com/maps/api/js 网址指向 Javascript 文件所在的位置,该文件会载入使用第 3 版 Google Maps API 所需的全部符号和定义。您的网页必须包含指向该网址的 script 标签。 此标头中的 <meta> 标签会指定如下内容:即应当以全屏模式显示该地图,且用户不能调整地图尺寸。(有关详细信息,请参见开发移动设备部分。) 请注意,我们还需要设置 sensor 参数,以指明此应用程序是否使用传感器确定用户的位置。在此示例中,我们将该参数设为变量“set_to_true_or_false”,用于强调您必须将该值显式设为 true 或 false。 地图 DOM 元素 <div id="map_canvas" style="width: 100%; height: 100%"></div> 要在网页上显示地图,我们必须为其留出一个位置。通常,我们的做法是创建一个名为 div 的元素,然后在浏览器的文档对象模型 (DOM) 中获取此元素的引用。 在上述示例中,我们定义了名为“map_canvas”的 <div> 并使用样式属性设置其大小。请注意,该尺寸已设置为“100%”,这将会展开地图,使之符合移动设备的屏幕尺寸。您可能需要根据浏览器的屏幕尺寸和填充区域调整这些值。请注意,地图总是会根据其中所包含的元素的大小决定其本身的尺寸,因此,您必须始终在 <div> 上显式设置一个适用的尺寸。 地图选项 var myLatlng = new google.maps.LatLng(-34.397, 150.644); var myOptions = { zoom: 8, center: myLatlng, mapTypeId: google.maps.MapTypeId.ROADMAP }; 要初始化地图,我们需要先创建一个包含地图初始化变量的 Map options 对象。该对象不是构建出来的,而是以对象常量的形式创建出来的。由于我们要将地图的中心设定为某一特定的点,因此,我们还需要创建一个 latlng 值,以保存此位置信息并将其传递到地图的选项中。有关指定位置的详细信息,请参阅下面的 纬度和经度部分。 我们还设置了初始缩放级别,并将 mapTypeId 设置为 google.maps.MapTypeId.ROADMAP。系统支持以下类型: • ROADMAP,用于显示 Google Maps 默认的普通二维图块。 • SATELLITE,用于显示拍摄的图块。 • HYBRID,用于同时显示拍摄的图块和突出特征(道路、城市名)图块层。 • TERRAIN,用于显示自然地形图块,自然地形图块中会显示高度和水体特征(山脉、河流等)。 与 Google Maps 第 2 版 API 不同的是,第 3 版中没有设置默认地图类型。您必须明确设置一个初始地图类型,才能查看相应的图块。 google.maps.Map - 基本对象 var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); Map 类是表示地图的 JavaScript 类。此类的对象定义了网页上的单个地图。(您可以创建此类的多个实例,每个对象都将在网页上定义一个单独的地图。)我们使用 Javascript new 操作符创建此类的一个新实例。 创建新的地图实例时,您需要在网页中指定一个 <div> HTML 元素作为地图的容器。HTML 节点是 Javascript document 对象的子对象,而且我们通过 document.getElementById() 方法获得该元素的引用。 此代码可定义一个名为 map 的变量,然后将该变量分配给新的 Map 对象,同时将该变量传递到在 myOptions 对象常量内定义的选项中。这些选项将会用于初始化地图的属性。Map() 函数称为“构造函数”,其定义如下: 构造函数 说明 google.maps.Map( opts?) 使用 opts 参数中已传递的可选参数创建新地图。 载入地图 <body onload="initialize()"> 呈现 HTML 网页时,会扩展文档对象模型 (DOM),接收任何外部图像和脚本并将其合并到 document 对象中。为了确保系统在完全载入网页后才将我们的地图添加到网页上,我们只会在 HTML 网页的 <body> 元素收到 onload 事件后,才会执行用于构建 Map 对象的函数。这样做可以避免出现不可预期的行为,并使我们可以对地图绘制的方式和时间进行更多控制。 body 标签的 onload 属性是事件处理程序的一个示例。Google Maps Javascript API 还提供了一组事件,可供您进行处理以确定状态变化。有关详细信息,请参阅地图事件部分。 查看示例 (map-simple.html) 纬度和经度 我们还需要一种引用各种地图位置的方法。在 Google Maps API 中,google.maps.LatLng 对象提供了此类机制。您可以构建一个 LatLng 对象,以 {纬度, 经度} 的顺序传递其参数: var myLatlng = new google.maps.LatLng(myLatitude, myLongitude) 请注意:将“地址”转变为地理地点的过程叫做“地址解析”。此版本的 Google Maps API 可支持地址解析。有关详细信息,请参见服务部分中的地址解析。 LatLng 对象在 Google Maps API 中用途广泛。例如,google.maps.Marker 对象会在其构造函数中应用 LatLng,并在地图上所指定的地理位置上添加标记 叠加层。 地图类型 Google Maps API 中提供了多种地图类型。除了用户熟悉的“绘制”道路地图图块,Google Maps API 还可支持其他地图类型。这些地图类型是通过使用 mapTypeId 属性,在地图的 Map options 对象中设置的。 Google Maps API 提供了以下地图类型: • MapTypeId.ROADMAP,用于显示默认的道路地图视图 • MapTypeId.SATELLITE,用于显示 Google 地球卫星图像 • MapTypeId.HYBRID,用于同时显示普通视图和卫星视图 • MapTypeId.TERRAIN,用于根据地形信息显示实际地图。 您可以通过调用地图的 setMapTypeId() 方法更改地图的类型。
用户界面事件 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 clickedLocation = new google.maps.LatLng(location); var marker = new google.maps.Marker({ position: location, map: map }); map.setCenter(location); }
在事件侦听器中使用闭包 在执行事件侦听器时,通常可取的做法是将私有数据和持久性数据附加到对象中。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); }); }
获取和设置事件处理程序中的属性 在系统触发事件时,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); } }); }
停用默认用户界面 有时,您可能希望关闭 API 的默认用户界面设置。要进行上述操作,请将 Map 的 disableDefaultUI 属性(在 Map options 对象中)设置为 true。此属性可停用 Google Maps API 中所有自动执行的用户界面行为。 以下代码可彻底停用默认用户界面: function initialize() { var myOptions = { zoom: 4, center: new google.maps.LatLng(-33, 151), disableDefaultUI: true, mapTypeId: google.maps.MapTypeId.ROADMAP } var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); }
下面的示例显示了一个简单的地图,其中启用了位于不同位置的所有控件。 function initialize() { var myOptions = { zoom: 12, center: new google.maps.LatLng(-28.643387, 153.612224), mapTypeId: google.maps.MapTypeId.ROADMAP, mapTypeControl: true, mapTypeControlOptions: { style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR, position: google.maps.ControlPosition.BOTTOM }, navigationControl: true, navigationControlOptions: { style: google.maps.NavigationControlStyle.ZOOM_PAN, position: google.maps.ControlPosition.TOP_RIGHT }, scaleControl: true, scaleControlOptions: { position: google.maps.ControlPosition.TOP_LEFT } } var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); }
绘制自定义控件 如何绘制控件由您自己决定。一般来讲,我们建议您将所有控件的显示方式放在一个单独的 <div> 元素中,以便可以将控件作为一个单元进行处理。我们将在下面所示的示例中使用这种设计模式。 设计具有吸引力的控件需要具备一些 CSS 和 DOM 结构方面的知识。以下代码显示了如何通过一个 <div> 容器、一个承载按钮轮廓的 <div> 和另一个承载按钮内部事项的 <div> 创建一个简单的控件。 // Create a div to hold the control. var controlDiv = document.createElement('DIV'); // Set CSS styles for the DIV containing the control // Setting padding to 5 px will offset the control // from the edge of the map controlDiv.style.padding = '5px'; // Set CSS for the control border var controlUI = document.createElement('DIV'); controlUI.style.backgroundColor = 'white'; controlUI.style.borderStyle = 'solid'; controlUI.style.borderWidth = '2px'; controlUI.style.cursor = 'pointer'; controlUI.style.textAlign = 'center'; controlUI.title = 'Click to set the map to Home'; controlDiv.appendChild(controlUI); // Set CSS for the control interior var controlText = document.createElement('DIV'); controlText.style.fontFamily = 'Arial,sans-serif'; controlText.style.fontSize = '12px'; controlText.style.paddingLeft = '4px'; controlText.style.paddingRight = '4px'; controlText.innerHTML = 'Home'; controlUI.appendChild(controlText);
处理自定义控件的事件 要使控件有用,它必须能够实际完成某些任务。控件的用途由您确定。控件可以响应用户输入,也可以响应 Map 的状态变化。 对于响应用户输入,Google Maps API 提供了一个跨浏览器的事件处理方法 addDomListener(),它可以处理浏览器的多数支持的 DOM 事件。以下代码段为浏览器的 'click' 事件添加了一个侦听器。请注意,此事件是从 DOM 接收的,而不是从地图。 // Setup the click event listener: simply set the map to // center on Chicago var chicago = new google.maps.LatLng(41.850033, -87.6500523); google.maps.event.addDomListener(outer, 'click', function() { map.setCenter(chicago) });
定位自定义控件 要在地图上定位自定义控件,您可以在 Map 对象的 controls 属性中将其放在适当位置。此属性包含一个 google.maps.ControlPosition 数组。您可以通过将 Node(通常是 <div>)添加至适当 ControlPosition 向地图中添加自定义控件。(有关这些位置的信息,请参见上面的控件定位。) 每个 ControlPosition 会存储一个显示在该位置的控件的 MVCArray。因此,当您向该位置添加或从中删除控件时,API 将相应更新控件。 API 按照 index 属性的顺序将控件放在每个位置,并会首先放置索引值较低的控件。例如,位置 BOTTOM_RIGHT 处的两个自定义控件将按照此索引顺序进行排列,并优先放置索引值较低的控件。默认情况下,所有自定义控件将在放置完任何 API 默认控件之后进行放置。您可以通过将控件的 index 属性设置为一个负值覆盖此行为。请注意,如果希望在放置相同位置的默认 API 控件“之前”放置您的控件,通常只需设置一个索引值。 以下代码将创建一个新的自定义控件(未显示其构造函数)并将其添加到地图中的 TOP_RIGHT 位置。 var map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions); // Construct your control in whatever manner is appropriate. // Generally, your constructor will want access to the // DIV on which you'll attach the control UI to the Map. var controlDiv = document.createElement('DIV'); var myControl = new MyControl(controlDiv); // We don't really need to set an index value here, but // this would be how you do it. Note that we set this // value as a property of the DIV itself. controlDiv.index = 1; // Add the control to the map at a designated control position // by pushing it on the position's array. This code will // implicitly add the control to the DOM, through the Map // object. You should not attach the control manually. map.controls[google.maps.ControlPosition.TOP_RIGHT].push(controlDiv);
自定义控件示例 下面是一个简单的控件(尽管不是很实用),其中综合了上面所示的模式。该控件通过将地图在某个默认位置居中来响应 DOM 'click' 事件: var map; var chicago = new google.maps.LatLng(41.850033, -87.6500523); /** * The HomeControl adds a control to the map that simply * returns the user to Chicago. This constructor takes * the control DIV as an argument. */ function HomeControl(controlDiv, map) { // Set CSS styles for the DIV containing the control // Setting padding to 5 px will offset the control // from the edge of the map controlDiv.style.padding = '5px'; // Set CSS for the control border var controlUI = document.createElement('DIV'); controlUI.style.backgroundColor = 'white'; controlUI.style.borderStyle = 'solid'; controlUI.style.borderWidth = '2px'; controlUI.style.cursor = 'pointer'; controlUI.style.textAlign = 'center'; controlUI.title = 'Click to set the map to Home'; controlDiv.appendChild(controlUI); // Set CSS for the control interior var controlText = document.createElement('DIV'); controlText.style.fontFamily = 'Arial,sans-serif'; controlText.style.fontSize = '12px'; controlText.style.paddingLeft = '4px'; controlText.style.paddingRight = '4px'; controlText.innerHTML = 'Home'; controlUI.appendChild(controlText); // Setup the click event listeners: simply set the map to // Chicago google.maps.event.addDomListener(controlUI, 'click', function() { map.setCenter(chicago) }); } function initialize() { var mapDiv = document.getElementById('map_canvas'); var myOptions = { zoom: 12, center: chicago, mapTypeId: google.maps.MapTypeId.ROADMAP } map = new google.maps.Map(mapDiv, myOptions); // Create the DIV to hold the control and // call the HomeControl() constructor passing // in this DIV. var homeControlDiv = document.createElement('DIV'); var homeControl = new HomeControl(homeControlDiv, map); homeControlDiv.index = 1; map.controls[google.maps.ControlPosition.TOP_RIGHT].push(homeControlDiv); }
为控件添加状态 控件也可以存储状态。下面的示例与前面所示的类似,但该控件包含了一个额外的“Set Home”按钮,它将控件设置为显示一个新首页位置。为此,我们在该控件内创建一个 home_ 属性以存储此状态,并为该状态提供了获取函数和设置函数。 var map; var chicago = new google.maps.LatLng(41.850033, -87.6500523); /** * The HomeControl adds a control to the map that * returns the user to the control's defined home. */ // Define a property to hold the Home state HomeControl.prototype.home_ = null; // Define setters and getters for this property HomeControl.prototype.getHome = function() { return this.home_; } HomeControl.prototype.setHome = function(home) { this.home_ = home; } function HomeControl(map, div, home) { // Get the control DIV. We'll attach our control // UI to this DIV. var controlDiv = div; // We set up a variable for the 'this' keyword // since we're adding event listeners later // and 'this' will be out of scope. var control = this; // Set the home property upon construction control.home_ = home; // Set CSS styles for the DIV containing the control // Setting padding to 5 px will offset the control // from the edge of the map controlDiv.style.padding = '5px'; // Set CSS for the control border var goHomeUI = document.createElement('DIV'); goHomeUI.title = 'Click to set the map to Home'; controlDiv.appendChild(goHomeUI); // Set CSS for the control interior var goHomeText = document.createElement('DIV'); goHomeText.innerHTML = 'Home'; goHomeUI.appendChild(goHomeText); // Set CSS for the setHome control border var setHomeUI = document.createElement('DIV'); setHomeUI.title = 'Click to set Home to the current center'; controlDiv.appendChild(setHomeUI); // Set CSS for the control interior var setHomeText = document.createElement('DIV'); setHomeText.innerHTML = 'Set Home'; setHomeUI.appendChild(setHomeText); // Setup the click event listener for Home: // simply set the map to the control's current home property. google.maps.event.addDomListener(goHomeUI, 'click', function() { var currentHome = control.getHome(); map.setCenter(currentHome); }); // Setup the click event listener for Set Home: // Set the control's home to the current Map center. google.maps.event.addDomListener(setHomeUI, 'click', function() { var newHome = map.getCenter(); control.setHome(newHome); }); } function initialize() { var mapDiv = document.getElementById('map_canvas'); var myOptions = { zoom: 12, center: chicago, mapTypeId: google.maps.MapTypeId.ROADMAP } map = new google.maps.Map(mapDiv, myOptions); // Create the DIV to hold the control and // call the HomeControl() constructor passing // in this DIV. var homeControlDiv = document.createElement('DIV'); var homeControl = new HomeControl(map, homeControlDiv, chicago); homeControlDiv.index = 1; map.controls[google.maps.ControlPosition.TOP_RIGHT].push(homeControlDiv);
添加叠加层 叠加层通常在构造时添加到地图中。所有叠加层都会定义构造中所用的 Options 对象,以指定应显示叠加层的地图。您也可以使用叠加层的 setMap() 方法,将其传递给要添加叠加层的地图,从而直接在地图上添加叠加层。 var myLatlng = new google.maps.LatLng(-25.363882,131.044922); var myOptions = { zoom: 4, center: myLatlng, mapTypeId: google.maps.MapTypeId.ROADMAP, } var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); var marker = new google.maps.Marker({ position: myLatlng, title:"Hello World!" }); // To add the marker to the map, call setMap(); marker.setMap(map); 删除叠加层 要从地图上删除叠加层,可调用叠加层的 setMap() 方法,传递 null。请注意,调用此方法不会删除叠加层,而只是从地图上删除叠加层。如果您要删除叠加层,则应当从地图上删除叠加层,然后将叠加层设置为 null。 如果您要管理一组叠加层,则应当创建一个数组以存储这些叠加层。使用数组后,只要您需要删除叠加层,就可以对数组中的每个叠加层调用 setMap()。(请注意,与第 2 版不同,该版本中未提供 clearOverlays() 方法。对于跟踪叠加层并在不需要时将其从地图中删除的任务,您需要自己执行。)要删除叠加层,您可以从地图上删除叠加层并将数组的 length 设置为 0,但此操作会删除对叠加层的所有引用。 下面示例的效果是点击地图时将标记放在地图上,然后将标记放入数组中。叠加层稍后可以删除、显示或删除: var map; var markersArray = []; function initialize() { var haightAshbury = new google.maps.LatLng(37.7699298, -122.4469157); var mapOptions = { zoom: 12, center: haightAshbury, mapTypeId: google.maps.MapTypeId.TERRAIN }; map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions); google.maps.event.addListener(map, 'click', function(event) { addMarker(event.latLng); }); } function addMarker(location) { marker = new google.maps.Marker({ position: location, map: map }); markersArray.push(marker); } // Removes the overlays from the map, but keeps them in the array function clearOverlays() { if (markersArray) { for (i in markersArray) { markersArray[i].setMap(null); } } } // Shows any overlays currently in the array function showOverlays() { if (markersArray) { for (i in markersArray) { markersArray[i].setMap(map); } } } // Deletes all markers in the array by removing references to them function deleteOverlays() { if (markersArray) { for (i in markersArray) { markersArray[i].setMap(null); } markersArray.length = 0; } }
标记 标记用于标识地图上的位置。默认情况下,标记使用的是标准图标,但您可以在标记的构造函数中设置一个自定义图标,或者通过对标记调用 setIcon() 设置一个自定义图标。google.maps.Marker 构造函数采用的是用于指定标记初始属性的一个 Marker options 对象常量。以下字段特别重要,通常是在您构建标记时进行设置的: • position(必需),用于指定标识标记初始位置的 LatLng。 • map(可选),用于指定要在其上设置标记的 Map 对象。 请注意,您应在 Marker 构造函数指定要为哪个地图添加标记。如果您不指定此参数,那么,您只能创建标记,而无法将其附加到地图上(或在地图上显示)。稍后,您可以通过调用标记的 setMap() 方法添加该标记。要删除标记,请调用将 null 作为参数传递的 setMap() 方法。 标记设计为可交互。例如,默认情况下它们接收 'click' 事件,常用于在事件侦听器中打开信息窗口。 以下示例介绍了如何将一个简单的标记添加到澳大利亚中心区域的乌鲁鲁的地图上: var myLatlng = new google.maps.LatLng(-25.363882,131.044922); var myOptions = { zoom: 4, center: myLatlng, mapTypeId: google.maps.MapTypeId.ROADMAP } var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); var marker = new google.maps.Marker({ position: myLatlng, map: map, title:"Hello World!" }); 此 Marker 标题将会以提示的形式显示。 如果您不想在标记的构造函数中传递任何 Marker options,那么,请在构造函数的最后一个参数中传递一个空对象 {}。
图标 标记可以定义要显示的图标,从而取代默认的图标。定义图标的过程中包含设置若干可定义标记视觉行为的属性。 简单图标 就最基本的情况而言,只需将标记的 icon 属性设置为某一图像的网址,图标便可指明要使用的图像(而非默认的 Google Maps 图钉图标)。在这种情况下,Google Maps API 将会自动调整图标的大小。 在以下示例中,我们会创建一个图标,用于标示澳大利亚悉尼的邦迪海滩的位置: function initialize() { var myLatlng = new google.maps.LatLng(-25.363882,131.044922); var myOptions = { zoom: 4, center: myLatlng, mapTypeId: google.maps.MapTypeId.ROADMAP } var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); var image = 'beachflag.png'; var myLatLng = new google.maps.LatLng(-33.890542, 151.274856); var beachMarker = new google.maps.Marker({ position: myLatLng, map: map, icon: image }); }
复杂图标 较为复杂的图标可用于指定复杂的形状(表示用户可点击的区域)、添加阴影图像,以及指定这些形状与其他叠加层在显示时应采用的“堆叠顺序”。以这种方式指定的图标应当将自己的 icon 属性和 shadow 属性设置为 MarkerImage 类型的对象。 阴影图像通常应该和主图像成 45 度夹角(向右上方倾斜),并且阴影图像的左下角应与图标图像的左下角对齐。阴影图像应是半透明的 24 位 PNG 图像,这样图像边界便可以在地图上正确显示。 MarkerImage 对象不仅可以定义图像,还可定义图标的 size、图标的 origin(例如,在您所需的图像取自一张较大的拼合图像时)以及图标热点所应定位的 anchor(取决于原点)。 以下示例介绍了如何创建复杂的标记,以表示澳大利亚新南威尔士的悉尼附近的海滩。请注意,应当将 anchor 设置为 (0,32),从而与旗杆的基座相对应。 function initialize() { var myOptions = { zoom: 10, center: new google.maps.LatLng(-33.9, 151.2), mapTypeId: google.maps.MapTypeId.ROADMAP } var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); setMarkers(map, beaches); } /** * Data for the markers consisting of a name, a LatLng and a zIndex for * the order in which these markers should display on top of each * other. */ var beaches = [ ['Bondi Beach', -33.890542, 151.274856, 4], ['Coogee Beach', -33.923036, 151.259052, 5], ['Cronulla Beach', -34.028249, 151.157507, 3], ['Manly Beach', -33.80010128657071, 151.28747820854187, 2], ['Maroubra Beach', -33.950198, 151.259302, 1] ]; function setMarkers(map, locations) { // Add markers to the map // Marker sizes are expressed as a Size of X,Y // where the origin of the image (0,0) is located // in the top left of the image. // Origins, anchor positions and coordinates of the marker // increase in the X direction to the right and in // the Y direction down. var image = new google.maps.MarkerImage('images/beachflag.png', // This marker is 20 pixels wide by 32 pixels tall. new google.maps.Size(20, 32), // The origin for this image is 0,0. new google.maps.Point(0,0), // The anchor for this image is the base of the flagpole at 0,32. new google.maps.Point(0, 32)); var shadow = new google.maps.MarkerImage('images/beachflag_shadow.png', // The shadow image is larger in the horizontal dimension // while the position and offset are the same as for the main image. new google.maps.Size(37, 32), new google.maps.Point(0,0), new google.maps.Point(0, 32)); // Shapes define the clickable region of the icon. // The type defines an HTML <area> element 'poly' which // traces out a polygon as a series of X,Y points. The final // coordinate closes the poly by connecting to the first // coordinate. var shape = { coord: [1, 1, 1, 20, 18, 20, 18 , 1], type: 'poly' }; for (var i = 0; i < locations.length; i++) { var beach = locations[i]; var myLatLng = new google.maps.LatLng(beach[1], beach[2]); var marker = new google.maps.Marker({ position: myLatLng, map: map, shadow: shadow, icon: image, shape: shape, title: beach[0], zIndex: beach[3] }); } }
地面叠加层 多边形在表示不规则的区域时很有用,但不能显示图片。如果要在地图上放置一幅图片,可以使用 GroundOverlay 对象。 GroundOverlay 的构造函数采用图片的网址和 LatLngBounds 作为参数。图片将渲染在地图上的指定边界内,并与地图的投影一致。 下面的示例将新泽西州纽瓦克的一幅老地图作为叠加层放在地图上: var newark = new google.maps.LatLng(40.740, -74.18); var imageBounds = new google.maps.LatLngBounds( new google.maps.LatLng(40.716216,-74.213393), new google.maps.LatLng(40.765641,-74.139235)); var myOptions = { zoom: 13, center: newark, mapTypeId: google.maps.MapTypeId.ROADMAP } var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); var oldmap = new google.maps.GroundOverlay( "http://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg", imageBounds); oldmap.setMap(map);
状态代码 status 代码可能返回下面的某个值: • google.maps.GeocoderStatus.OK 表示地址解析成功。 • google.maps.GeocoderStatus.ZERO_RESULTS 表示地址解析成功,但未返回结果。如果地址解析过程中传递的偏远位置 address 或 latng 并不存在,则会出现 种情况。 • google.maps.GeocoderStatus.OVER_QUERY_LIMIT 表示您超出了配额。 • google.maps.GeocoderStatus.REQUEST_DENIED 表示由于某种原因拒绝了您的请求。 • google.maps.GeocoderStatus.INVALID_REQUEST 通常表示缺少查询参数(address 或 latLng)。 在此示例中,我们对一个地址进行地址解析,并根据返回的纬度/经度值放置标记。请注意,处理程序以匿名函数显式声明的形式传递。 var geocoder; var map; function initialize() { geocoder = new google.maps.Geocoder(); var latlng = new google.maps.LatLng(-34.397, 150.644); var myOptions = { zoom: 8, center: latlng, mapTypeId: google.maps.MapTypeId.ROADMAP } map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); } function codeAddress() { var address = document.getElementById("address").value; if (geocoder) { geocoder.geocode( { 'address': address}, function(results, status) { if (status == google.maps.GeocoderStatus.OK) { map.setCenter(results[0].geometry.location); var marker = new google.maps.Marker({ map: map, position: results[0].geometry.location }); } else { alert("Geocode was not successful for the following reason: " + status); } }); } } <body onload="initialize()"> <div id="map_canvas" style="width: 320px; height: 480px;"></div> <div> <input id="address" type="textbox" value="Sydney, NSW"> <input type="button" value="Encode" onclick="codeAddress()"> </div> </body>
创建地图和用户界面 设置完后端功能之后,接下来就可以创建地图和用户界面功能。如果您从未创建过 Google Maps,请先尝试创建文档中介绍的一些基本示例,从而确保您掌握了创建地图的基础知识。 创建标记和信息窗口 创建地图并使地图居中,然后,为该地图分配一个 click 侦听器。在侦听器的回调函数中,在点击过的坐标处创建一个标记,并在发送至构造函数的 GMarkerOptions 对象中将 draggable 属性设置为 "true"。然后,为该标记分配一个 click 侦听器,用于在标记上方弹出一个信息窗口。此信息窗口含有某一表单的 HTML 代码,该表单包含几个文本字段、一个下拉列表及一个保存按钮。如下所述,每个表单输入项都对应一个 ID,而且,保存按钮具有一个 onclick 侦听器,用于调用 saveData 函数。 保存数据 在信息窗口按钮所调用的 saveData 函数中,您可以执行以下操作: • 保存标记坐标的值和所有表单元素(如有需要,请转义为易于访问的网址)。 • 将 PHP 文件名、参数及其相应的值合在一起,形成一个网址。 • 将该网址作为 GDownloadUrl 的第一个参数进行传递,这个由 API 提供的函数会封装 XMLHTTPRequest 对象,该对象能让您通过 Javascript 检索各种文件(通常为 XML 格式)。GDownloadUrl 回调函数将会为您提供相应网址的内容及状态代码。 • 检查并确保返回的状态代码为 200。这表示已成功地检索到该文件,我们可以继续进行处理了。 • 检查返回的数据字符串的长度,空数据文件表示未输出任何错误的字符串。如果字符串长度接近零,您可以关闭信息窗口,然后输出操作已成功的消息。 执行以上所有操作的 HTML 文件如下所示 (phpsqlinfo_add.html): <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <title>Google Maps JavaScript API Example: Simple Map</title> <script src="http://maps.google.com/maps?file=api&v=2.x&key=ABQIAAAAjU0EJWnWPMv7oQ-jjS7dYxTPZYElJSBeBUeMSX5xXgq6lLjHthSAk20WnZ_iuuzhMt60X_ukms-AUg" type="text/javascript"></script> <script type="text/javascript"> var marker; function initialize() { if (GBrowserIsCompatible()) { 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) { marker = new GMarker(latlng, {draggable:true}); GEvent.addListener(marker, "click", function() { var html = "<table>" + "<tr><td>Name:</td> <td><input type='text' id='name'/> </td> </tr>" + "<tr><td>Address:</td> <td><input type='text' id='address'/></td> </tr>" + "<tr><td>Type:</td> <td><select id='type'>" + "<option value='bar' SELECTED>bar</option>" + "<option value='restaurant'>restaurant</option>" + "</select> </td></tr>" + "<tr><td></td><td><input type='button' value='Save & Close' onclick='saveData()'/></td></tr>"; marker.openInfoWindow(html); }); map.addOverlay(marker); } }); } } function saveData() { var name = escape(document.getElementById("name").value); var address = escape(document.getElementById("address").value); var type = document.getElementById("type").value; var latlng = marker.getLatLng(); var lat = latlng.lat(); var lng = latlng.lng(); var url = "phpsqlinfo_addrow.php?name=" + name + "&address=" + address + "&type=" + type + "&lat=" + lat + "&lng=" + lng; GDownloadUrl(url, function(data, responseCode) { if (responseCode == 200 && data.length <= 1) { marker.closeInfoWindow(); document.getElementById("message").innerHTML = "Location added."; } }); } </script> </head> <body onload="initialize()" onunload="GUnload()"> <div id="map_canvas" style="width: 500px; height: 300px"></div> <div id="message"></div> </body> </html> 在打开信息窗口时,地图应如下所示:
每当夜深人静的时候,想想今天发生了什么,失去了什么,得到了什么,做了什么,没做什么,该做什么,不该做什么,明天要做什么!