绘图库
本文档中的概念仅适用于 google.maps.drawing
库中提供的地图项。默认情况下,系统在加载 Maps JavaScript API 时不会加载该库,您必须使用 libraries
引导程序参数进行明确指定。
http://maps.googleapis.com/maps/api/js?sensor=false&libraries=drawing
DrawingManager
类提供了一个图形界面,以供用户在地图上绘制多边形、矩形、折线、圆形和标记。DrawingManager
对象以如下方式创建:
var drawingManager = new google.maps.drawing.DrawingManager(); drawingManager.setMap(map);
DrawingManager 选项
DrawingManager
构造函数采用一组选项,以定义要显示的控件集、控件的位置以及初始绘图状态。
-
DrawingManager
的drawingMode
属性用于定义 DrawingManager 的初始绘图状态。该属性接受google.maps.drawing.OverlayType
常量,且默认为null
(在此情况下启动 DrawingManager 时,光标会处于非绘图模式)。 -
DrawingManager
的drawingControl
属性用于定义地图上的绘图工具选择界面的可见性。该属性接受布尔值。 - 您还可以使用
DrawingManager
的drawingControlOptions
属性,定义控件的位置以及控件中应表示的叠加层的类型。-
position
用于定义绘图控件在地图上的位置,且接受google.maps.ControlPosition
常量。 -
drawingModes
是一组google.maps.drawing.OverlayType
常量,且用于定义绘图控件形状选择器中包含的叠加层类型。系统将始终显示手形图标,以便用户无需绘图即可与地图进行交互。
-
- 您可为每种叠加层类型都指定一组默认属性,以便定义首次创建相应叠加层时所采用的外观。这些属性可在叠加层的
{overlay}Options
属性(其中{overlay}
表示叠加层的类型)中进行定义。例如,圆形的填充属性、笔触属性、zIndex 和可点击性可使用circleOptions
属性进行定义。如果已传递任何大小、位置或地图值,则系统会忽略这些默认属性。
var drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.MARKER,
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [google.maps.drawing.OverlayType.MARKER, google.maps.drawing.OverlayType.CIRCLE]
},
markerOptions: {
icon: new google.maps.MarkerImage('http://www.example.com/icon.png')
},
circleOptions: {
fillColor: '#ffff00',
fillOpacity: 1,
strokeWeight: 5,
clickable: false,
zIndex: 1,
editable: true
}
});
drawingManager.setMap(map);
更新绘图工具控件
创建 DrawingManager
对象后,您可调用 setOptions()
并传递新的值,以进行更新。
drawingManager.setOptions({
drawingControlOptions: {
position: google.maps.ControlPosition.BOTTOM_LEFT,
drawingModes: [google.maps.drawing.OverlayType.MARKER]
}
});
使用以下方法即可隐藏或显示绘图工具控件:
// To hide:
drawingManager.setOptions({
drawingControl: false
});
// To show:
drawingManager.setOptions({
drawingControl: true
});
要从
map
对象删除绘图工具控件,请使用以下方法:
drawingManager.setMap(null);
隐藏绘图控件会导致绘图工具控件无法显示,不过
DrawingManager
类的所有功能仍然可用。这样即可实现您自己的控件(如有必要)。从map
对象删除DrawingManager
会导致所有绘图功能停用;要恢复绘图地图项,请务必使用drawingManager.setMap(map)
将DrawingManager
对象重新附加到地图,或者构造新的该对象。绘图事件
创建形状叠加层后,会触发以下两个事件:
-
{overlay}complete
事件(其中{overlay}
代表叠加层类型,例如circlecomplete
、polygoncomplete
等)。对相应叠加层的引用会作为参数进行传递。 -
overlaycomplete
事件。包含OverlayType
和对相应叠加层的引用的对象常量会作为参数进行传递。
google.maps.event.addListener(drawingManager, 'circlecomplete', function(circle) {
var radius = circle.getRadius();
});
google.maps.event.addListener(drawingManager, 'overlaycomplete', function(event) {
if (event.type == google.maps.drawing.OverlayType.CIRCLE) {
var radius = event.overlay.getRadius();
}
});
信息窗口
InfoWindow
用于在地图上方以浮动窗口的形式显示内容。信息窗口有点像漫画书上的文字气泡框,它有一个内容区域和一条锥形引线,引线的头位于地图的指定位置上。点击
Google 地图上的商户标记后,您就可以看到活动的信息窗口了。
InfoWindow
构造函数采用 InfoWindow
options
对象,以指定一组关于信息窗口的显示方式的初始参数。创建完毕后,所生成的信息窗口不会添加到地图上。要显示该信息窗口,您需要对 InfoWindow
调用 open()
方法,并向其传递要在其上打开信息窗口的 Map
,以及用于锚定该信息窗口的 Marker
(可选)。(如果未提供任何标记,则会在该信息窗口的 position
属性处将其打开。)
InfoWindow
options
对象是一个包含以下字段的对象常量:
-
content
,其中包含要在信息窗口打开后显示在其中的文本字符串或 DOM 节点。 -
pixelOffset
,其中包含从信息窗口的尖端到其锚定位置的偏移量。实际上,您无需修改此字段。 -
position
,其中包含此信息窗口锚定位置处的LatLng
。请注意,在标记上打开信息窗口后,系统会自动使用一个新位置更新该值。 -
maxWidth
,用于指定信息窗口的最大宽度(以像素为单位)。默认情况下,信息窗口会根据其内容进行扩展,并且如果是为填充地图而进行扩展的,则其文本会自动换行。如果您实现了maxWidth
,那么信息窗口将会自动换行以强制适应像素宽度。如果屏幕的实际使用面积允许的话,那么信息窗口在达到最大宽度后仍然可以垂直扩展。
InfoWindow
的内容可以是文本字符串、HTML 代码段,也可以就是 DOM 元素。要设置此内容,请在 InfoWindow
options
构造函数中传递该内容,或者对信息窗口显式调用setContent()
。要显式调整内容的大小,您可以使用 <div>
进行调整,或者启用滚动功能(如果您希望的话)。请注意,如果您没有启用滚动功能,且内容的大小又超出了信息窗口的可用空间,那么内容可能会从信息窗口中“溢”出。
您可以将 InfoWindow
附加到 Marker
对象(在此情况下,信息窗口的位置取决于标记的位置)上,或者地图上所指定的 LatLng
位置。如果您一次只想显示一个信息窗口(正如
Google 地图上的相应行为),只需创建一个信息窗口,然后在地图事件(例如用户点击)完毕后将其重新分配到不同的位置或标记即可。不过与 Google Maps API V2 中的相应行为不同,如果您选择执行以上操作,那么地图可能会立即显示多个 InfoWindow
对象。
要更改某个信息窗口的位置,您可以对该信息窗口调用 setPosition()
以显式更改其位置,或者使用 InfoWindow.open()
方法将其附加到新标记。请注意,如果您在没有传递标记的情况下调用了 open()
,那么 InfoWindow
将会使用构建完毕后通过 InfoWindow
options
对象所指定的位置。
以下代码显示了澳大利亚中心位置的标记。点击该标记可显示信息窗口。
var myLatlng = new google.maps.LatLng(-25.363882,131.044922);
var mapOptions = {
zoom: 4,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
var contentString = '<div id="content">'+
'<div id="siteNotice">'+
'</div>'+
'<h2 id="firstHeading" class="firstHeading">Uluru</h2>'+
'<div id="bodyContent">'+
'<p><b>Uluru</b>, also referred to as <b>Ayers Rock</b>, is a large ' +
'sandstone rock formation in the southern part of the '+
'Northern Territory, central Australia. It lies 335 km (208 mi) '+
'south west of the nearest large town, Alice Springs; 450 km '+
'(280 mi) by road. Kata Tjuta and Uluru are the two major '+
'features of the Uluru - Kata Tjuta National Park. Uluru is '+
'sacred to the Pitjantjatjara and Yankunytjatjara, the '+
'Aboriginal people of the area. It has many springs, waterholes, '+
'rock caves and ancient paintings. Uluru is listed as a World '+
'Heritage Site.</p>'+
'<p>Attribution: Uluru, <a href="http://en.wikipedia.org/w/index.php?title=Uluru&oldid=297882194">'+
'http://en.wikipedia.org/w/index.php?title=Uluru</a> (last visited June 22, 2009).</p>'+
'</div>'+
'</div>';
var infowindow = new google.maps.InfoWindow({
content: contentString
});
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title:"Uluru (Ayers Rock)"
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map,marker);
});
地面叠加层
多边形在表示不规则的区域时很有用,但不能显示图片。要在地图上放置一张图片,请使用 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 mapOptions = {
zoom: 13,
center: newark,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
var oldmap = new google.maps.GroundOverlay(
"http://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg",
imageBounds);
oldmap.setMap(map);
自定义叠加层
Google Maps API V3 提供了用于创建自定义叠加层的 OverlayView
类。OverlayView
是一个基类,可为您提供在创建叠加层时必须实现的若干方法。该类还提供了一些方法,用于实现屏幕坐标和地图位置之间的转换。
要创建自定义叠加层,请执行以下操作:
-
将自定义对象的
prototype
设置为google.maps.OverlayView()
的新实例。这可以有效地实现叠加层类的“子类化”。 - 为自定义叠加层创建构造函数,并将该构造函数中的所有初始化参数都设置为自定义属性。
-
在原型中实现
onAdd()
方法,以将叠加层附加到地图。在地图准备好附加叠加层后,系统将会调用OverlayView.onAdd()
。 -
在原型中实现
draw()
方法,以处理对象的视觉显示。同样,在对象首次显示后,系统将会调用OverlayView.draw()
。 -
您还应实现
onRemove()
方法,以清理叠加层中添加的所有元素。
我们将会在以下各部分中逐步介绍这些操作。
叠加层的子类化
我们将会使用 OverlayView
创建简单的图片叠加层(类似于 V2 API 中的 GGroundOverlay
)。我们将创建一个 USGSOverlay
对象,其中包含了相关区域的
USGS 图片以及该图片的边界。
var overlay;
function initialize() {
var myLatLng = new google.maps.LatLng(62.323907, -150.109291);
var mapOptions = {
zoom: 11,
center: myLatLng,
mapTypeId: google.maps.MapTypeId.SATELLITE
};
var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
var swBound = new google.maps.LatLng(62.281819, -150.287132);
var neBound = new google.maps.LatLng(62.400471, -150.005608);
var bounds = new google.maps.LatLngBounds(swBound, neBound);
// Photograph courtesy of the U.S. Geological Survey
var srcImage = 'images/talkeetna.png';
overlay = new USGSOverlay(bounds, srcImage, map);
}
接下来,我们将创建一个该类的构造函数,并将已传递的参数初始化为新对象的属性。此外,我们还需要显式地将 OverlayView
中的 USGSOverlay
子类化。为此,我们会将新类的 prototype
设为相应父类的一个实例。(由于我们不希望修改父类,因此将此处的原型设为了实例,而非该父类。)function USGSOverlay(bounds, image, map) {
// Now initialize all properties.
this.bounds_ = bounds;
this.image_ = image;
this.map_ = map;
// We define a property to hold the image's
// div. We'll actually create this div
// upon receipt of the add() method so we'll
// leave it null for now.
this.div_ = null;
// Explicitly call setMap() on this overlay
this.setMap(map);
}
USGSOverlay.prototype = new google.maps.OverlayView();
目前,我们还无法在叠加层的构造函数中将此叠加层附加到地图上。具体而言,我们需要确保所有的地图窗格(用于指定对象在地图上的显示顺序)都可用。API 提供了一种帮助程序方法,可以非常方便地表明是否执行了上述操作。我们将会在下一部分中介绍如何处理该方法。
初始化叠加层
当叠加层完成首次示例化并处于准备显示状态时,我们需要通过浏览器的 DOM 将其附加到地图。API 会显示相关信息以表明:系统已通过调用叠加层的 onAdd()
方法将其添加到地图。在处理此方法时,我们会创建一个用于存储图片的 <div>
,然后添加一个 <img>
元素并将其附加到 <div>
,最后将叠加层附加到地图的一个“窗格”(即
DOM 树中的节点)。
一组 MapPanes
类型的窗格用于指定不同的层在地图上的堆叠顺序。您可以使用以下窗格,并按以下枚举顺序(由下至上,第一个窗格在最下面)堆叠这些窗格:
-
MapPanes.mapPane
-
MapPanes.overlayLayer
-
MapPanes.overlayShadow
-
MapPanes.overlayImage
-
MapPanes.floatShadow
-
MapPanes.overlayMouseTarget
-
MapPanes.floatPane
由于我们的图片为“地面叠加层”,因此将会使用 overlayLayer
地图窗格。创建该窗格后,我们将以子对象的形式向其附加对象。
USGSOverlay.prototype.onAdd = function() {
// Note: an overlay's receipt of onAdd() indicates that
// the map's panes are now available for attaching
// the overlay to the map via the DOM.
// Create the DIV and set some basic attributes.
var div = document.createElement('div');
div.style.border = "none";
div.style.borderWidth = "0px";
div.style.position = "absolute";
// Create an IMG element and attach it to the DIV.
var img = document.createElement("img");
img.src = this.image_;
img.style.width = "100%";
img.style.height = "100%";
div.appendChild(img);
// Set the overlay's div_ property to this DIV
this.div_ = div;
// We add an overlay to a map via one of the map's panes.
// We'll add this overlay to the overlayImage pane.
var panes = this.getPanes();
panes.overlayLayer.appendChild(div);
}
绘制叠加层
请注意,在上述操作中,我们实际上并未调用任何特殊的视觉显示。每当需要在地图上绘制叠加层时(包括首次添加叠加层时),API 都会对叠加层调用独立的 draw()
方法。
因此,我们将会实现此 draw()
方法,然后使用 getProjection()
检索叠加层的 MapCanvasProjection
,并计算对象的右上角和左下角锚定点的准确坐标,从而重新调整 <div>
的大小;同时,此操作还可重新调整图片的大小,以使其与我们在叠加层的构造函数中所指定的范围相匹配。
USGSOverlay.prototype.draw = function() {
// Size and position the overlay. We use a southwest and northeast
// position of the overlay to peg it to the correct position and size.
// We need to retrieve the projection from this overlay to do this.
var overlayProjection = this.getProjection();
// Retrieve the southwest and northeast coordinates of this overlay
// in latlngs and convert them to pixels coordinates.
// We'll use these coordinates to resize the DIV.
var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());
// Resize the image's DIV to fit the indicated dimensions.
var div = this.div_;
div.style.left = sw.x + 'px';
div.style.top = ne.y + 'px';
div.style.width = (ne.x - sw.x) + 'px';
div.style.height = (sw.y - ne.y) + 'px';
}
删除叠加层
我们还会添加 onRemove()
方法,以便从地图彻底删除叠加层。如果之前将叠加层的 map
属性设为了 null
,那么系统将会自动通过
API 调用此方法。
USGSOverlay.prototype.onRemove = function() {
this.div_.parentNode.removeChild(this.div_);
this.div_ = null;
}
隐藏和显示叠加层
如果您想要隐藏或显示(而不只是创建或删除)叠加层,您可实现自己的 hide()
和 show()
方法,以调整叠加层的可见性。此外,您也可以将叠加层与地图的
DOM 分离,不过此操作的成本略高。请注意,如果您随后将叠加层重新附加到了地图的 DOM,那么系统将会重新调用叠加层的 onAdd()
方法。
以下示例介绍了如何将 hide()
和 show()
方法添加到叠加层的原型,以切换容器 <div>
的可见性。此外,我们还添加了 toogleDOM()
方法,该方法可将叠加层附加到地图,或将两者分离开来。请注意,如果我们将可见性设为 "hidden"
,那么系统会通过 toggleDOM()
将地图与
DOM 分离;如果我们稍后重新附加了地图,那么叠加层会再次显示出来,这是因为我们利用叠加层的 onAdd()
方法重新创建了其中所包含的 <div>
。
// Note that the visibility property must be a string enclosed in quotes
USGSOverlay.prototype.hide = function() {
if (this.div_) {
this.div_.style.visibility = "hidden";
}
}
USGSOverlay.prototype.show = function() {
if (this.div_) {
this.div_.style.visibility = "visible";
}
}
USGSOverlay.prototype.toggle = function() {
if (this.div_) {
if (this.div_.style.visibility == "hidden") {
this.show();
} else {
this.hide();
}
}
}
USGSOverlay.prototype.toggleDOM = function() {
if (this.getMap()) {
this.setMap(null);
} else {
this.setMap(this.map_);
}
}
// Now we add an input button to initiate the toggle method
// on the specific overlay
<div id ="toolbar" width="100%; height:20px;" style="text-align:center">
<input type="button" value="Toggle Visibility" οnclick="overlay.toggle();"></input>
<input type="button" value="Toggle DOM Attachment" οnclick="overlay.toggleDOM();"></input>
</div>
<div id="map_canvas" style="width: 100%; height: 95%;"></div>