Google maps javascript api v3 叠加层(Overlays)介绍
很多人尝试google maps api的开发,通常会涉及到在Google maps上进行标注功能的开发。Helloj2ee学习一项技术通常不在看书,而是多以帮助为主。当我看完之后,我将Overlay这一章翻译成中文,和大家共享。该文英文全文是Google maps api javascript v3帮助,链接:https://developers.google.com/maps/documentation/javascript/overlays
相应会有一个中文的Google翻译:https://developers.google.com/maps/documentation/javascript/overlays?hl=zh-cn。但是这篇译文和Google的译文相比,会有如下不同:
1 我会保留诸如Overlay,marker保留其英文原文,通常该词第一次出现,我会以中文英文同时出现的方式,而第二次只保留英文;
2 代码中的英文注释将其翻译成了对应中文;
3 对于Google翻译中生硬的地方做了修改;
4 Google的中文文档帮助和英文文档帮助并不对应,我会英文中没有的对应翻译过来(目录中标红的地方)
5 由于众所周知的原因,大家未必能够很顺畅地浏览V3中的例子,我将该篇用到的示例一并打包。链接地址:http://vdisk.weibo.com/s/n5w3t
目录:
1 叠加层(Overlay)概述
1.1 添加Overlay
1.2 删除Overlay
2 符号(Symbol)
2.1 预定义路径(Path)
3 标注(Marker)
3.1 Marker动画
3.2 自定义Marker
3.2.1 简单图标(Icon)
3.2.2 复杂Icon
3.2.3 矢量Icon
4 折线(Polyline)
4.1 Polyline选项(Options)
4.2 Polyline数组
4.3 Polyline符号化
5 多边形(Polygon)
5.1 Polygon选项
5.2 Polygon自动闭合
5.3 Polygon数组
6 圆和矩形
6.1 圆
6.2 矩形
7 可编辑形状
7.1 编辑事件
8 绘图(Drawing)库
8.1 DrawingManager选项
8.2 图形绘制工具控件更新
8.3 绘图事件
9 信息窗口(info window)
10 Ground Overlays
11 自定义overlay
11.1 overlay的子类化
11.2 初始化自定义的overlay
11.3 自定义overlay的绘制
11.4 隐藏和显示自定义的overlay
1. 叠加层(Overlay)概述
Overlay是地图上有经纬坐标的对象集合,因此Overlay会随地图拖拽或缩放而移动。Overlay表示的是“添加”到地图上具有明确位置的点、线、面或者三者集合的对象。
Google Maps API有以下几种类型的Overlay:
- 使用Marker表示地图上单个位置的对象。Marker有时可显示自定义的图标,这时Marker又被称之为icon。Marker和icon我们都称之为marker对象。(有关详细信息参见下面的Marker和Icon节)
- 使用折线(Polyline)(一系列顺序排列的位置点集合)表示地图上的线段。线段就是一种类型的Polyline。
- 使用多边形(Polygon)表示地图上的不规则区域。Polygon类似于Polyline。与Polyline相同的是,多边形也是由一系列顺序排列的位置点构成;不同的是,Polygon定义的是一个闭合区域。(有关详细信息,请参见下面的Polygon节。)
- 地图图层可显示为overlay地图类型。您可以通过创建自定义地图类型以创建自己的图块集,该自定义地图类型可取代基本地图图块集,或作为overlay显示在现有基本地图图块集之上。(有关详细信息,请参见自定义地图类型。)
- 信息窗口(info window)也是特殊类型的Overlay,用于在地图特定位置上的弹出式提示框里显示信息(通常是文字或图片)(有关详细信息,请参见info window节。)
- 您还可以实现自定义的Overlay。这些自定义Overlay会实现 OverlayView 接口。(有关详细信息,请参见自定义Overlay节。)
1.1添加Overlay
Overlay通常在构造时,添加到地图中。所有的Overlay都定义了选项(Options)对象,来指定Overlay在哪个地图上显示。当然您也可以直接使用Overlay的SetMap方法,将Overlay添加到指定的地图上。
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!" }); // 调用setMap方法,将Marker添加到地图上 marker.setMap(map);
1.2 删除Overlay
要从地图上删除Overlay,同样可调用Overlay对象的 setMap() 方法,只是传递 null参数。请注意,调用此方法不会删除Overlay,而只是从地图上删除Overlay。如果您要真正删除Overlay,则应当从地图上删除Overlay,然后将Overlay设置为 null。
如果要管理一组Overlay对象,则应当创建一个数组来存储这些Overlay。使用数组时,如果需要删除Overlay,需要对数组中的每个Overlay依次调用 setMap()。(注意,与第 2 版不同,该版本中未提供 clearOverlays() 方法。您需要自己负责追踪Overlay的状态,并在不需要他们时,将其删除。)您可以通过在地图上依次移除Overlay,并将数组的长度(Length)设置为0,以此删除Overlay。但该操作会删除所有对Overlay的外部引用。
下面示例是单击地图时将Marker放在地图上,然后将Marker存入数组中。Overlay可以隐藏、显示或者删除:
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); } // 从地图中移除overlay,但仍然保存在数组中 function clearOverlays() { if (markersArray) { for (i in markersArray) { markersArray[i].setMap(null); } } } // 在数组中显示当前的overlay function showOverlays() { if (markersArray) { for (i in markersArray) { markersArray[i].setMap(map); } } } // 删除数组中所有的marker function deleteOverlays() { if (markersArray) { for (i in markersArray) { markersArray[i].setMap(null); } markersArray.length = 0; } }
查看示例 (overlay-remove.html)
2. 符号(Symbol)
Symbol是一种基于矢量的图像,它可以应用在Marker或者Polyline对象上。Symbol通过路径(path)来定义(使用SVG Path语法规则),其他选项控制Symbol如何显示。SymbolPath对象已经预定义了若干个Symbol。除了Path这个唯一必须设置的属性外,Symbol类还支持若干个显示设置的属性,比如画笔填充色以及画笔宽度等。
读者希望学习线要素符号化和动画的相关知识,请参见Polyline符号化一节。读者希望学习marker符号化的相关知识,请参见矢量Icon一节。
- Symbol类提供如下属性。注意Symbol的默认行为会因应用在Marker或者Polyline上,而略微有些变化。
- Path(必设置项),Path定义了Symbol的形状。您可以使用google.maps.SymbolPath内置的path对象或者使用SVG path语法规则自定义Path。注意:Polyline上定义的Path对象必须在22*22像素范围内,如果Path上的点在该范围外,那么必须将Scale属性调整为一个小数值(比如0.2),使得缩小后的点能够在该范围内。
- anchor,Symbol相对Marker或者Polyline的位置。Symbol的Path属性坐标以anchor的x和y为坐标原点,横轴左方为正,纵轴上方为正。默认Symbol的anchor坐标位置为(0,0)。该坐标和Symbol的Path属性在同一坐标系下。
- fillColor,Symbol的填充色。除去扩展命名的颜色外,fillcolor支持所有的CSS3的颜色。对于符号化的Marker而言,该属性默认为“黑色”。对于Polyline而言,该属性默认为相应的画笔颜色。
- fillOpacity,Symbol填充的透明度,该属性值在0和1之间,默认为0。
- rotation,Symbol旋转的角度,顺时针方向,以度为单位。默认marker的Symbol,rotation属性为0,Polyline上的symbol旋转角度取决于Polyline边的角度。对Polyline的Symbol设置rotation属性,这意味着该符号不会沿着Polyline边的方向。
- scale,符号尺寸的比例值。对于Marker的Symbol而言,该值默认为1。经过缩放后,该Symbol可以是任意尺寸。对于Polyline的Symbol而言,该值默认为笔宽。经过缩放后,Symbol必须在以anchor为中心,22*22像素区域内。
- strokecolor,符号画笔颜色。除去扩展命名的颜色外,fillcolor支持所有的CSS3的颜色。对于Marker的Symbol而言,默认值为“黑色”。对于Polyline的Symbol而言,该值默认为Polyline的画笔颜色。
- strokeOpacity,符号画笔的透明度,该属性值在0和1之间。对于Marker的Symbol而言,默认值为0。对于Polyline的Symbol而言,该值默认为Polyline的画笔透明度。
- strokeWeight,符号的画笔宽度。默认为Symbol的scale值。
下面示例创建了一个黄色五角星的Symbol,用浅黄色填充,并且用深黄色描边。
var goldStar = { path: 'M 125,5 155,90 245,90 175,145 200,230 125,180 50,230 75,145 5,90 95,90 z', fillColor: "yellow", fillOpacity: 0.8, scale: 1, strokeColor: "gold", strokeWeight: 14 }; var marker = new google.maps.Marker({ position: new google.maps.LatLng(-25.363, 131.044), icon: goldStar, map: map });
2.1 预定义路径(Path)
Google Maps JavaScript API提供内置的符号,可以应用在Marker或者Polyline上。默认的符号包括圆,两种类型的箭头。在Polyline上的Symbol方向是固定的,因此需要前方和后方两种箭头,前方是Polyline前进的方向。内置的Symbol如下表所示。
您也可以通过Symbol options修改内置符号的画笔或者填充属性。
3. 标注(Marker)
标注(Marker)用于标识地图上的位置。默认情况下,标注使用的是标准图标(Icon),但可以在标注的构造函数中设置一个自定义Icon,或者通过调用 setIcon方法 来设置一个自定义Icon。google.maps.Marker 构造函数采用了一个Marker options对象设置Marker的初始属性。在构造Marker时,下面的属性非常重要,而且经常会被设置。
- position(必需),用于指定Marker初始位置的经纬度 LatLng。
- map(可选),用于指定Marker在哪个Map 对象上。
注意,在 Marker构造函数中需要指定为哪个地图添加Marker。如果不指定该参数,那么,只能创建Marker,而无法将其添加到地图上(或显示在地图上)。但是可以在后面通过调用Marker的setMap()方法在地图上添加Marker。如果要移除Marker,则调用setMap()方法时,传递null参数。
Marker也可设计成交互的。比如,默认情况下它们接收 'click' 事件,常在该事件响应函数中弹出信息窗口。并且将Marker的draggable属性设置成true,就能够使Marker在地图上可拖拽。
以下示例介绍了如何将一个简单的Marker添加到澳大利亚中心区域的Uluru的地图上:
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 marker = new google.maps.Marker({ position: myLatlng, map: map, title:"Hello World!" });
Marker 标题将会以提示框(Tooltip)的形式显示。
如果不想在Marker的构造函数中传递任何 Marker options,那么,请在构造函数的参数中传递一个空对象 {}。
查看示例 (marker-simple.html)
3.1 Marker动画
您也可以对Marker添加动画效果,以便它们在各种不同的环境中展现动态运动效果。为Marker添加动画效果的方法是设置Marker的 animation 属性(该属性属于 google.maps.Animation 类型)。系统目前支持以下 Animation 值:
- DROP 表明Marker初次放置于地图上时,应当从地图顶端落到目标位置。当Marker停止移动时,动画也会立即结束,且 animation值还原为 null。通常,该类型动画应用在Marker 创建过程中。
- BOUNCE 表明Marker会在相应的位置上“弹跳”。Marker会不停“弹跳”,直到Marker的animation属性设置为null。
可以调用 Marker 对象的 setAnimation()方法,对现有Marker添加动画效果。
下面示例在瑞典斯德哥尔摩(Stockholm)市创建了一个采用 DROP 动画的Marker。点击该Marker时,可使它在 BOUNCE 动画和无动画之间切换:
var stockholm = new google.maps.LatLng(59.32522, 18.07002); var parliament = new google.maps.LatLng(59.327383, 18.06747); var marker; var map; function initialize() { var mapOptions = { zoom: 13, mapTypeId: google.maps.MapTypeId.ROADMAP, center: stockholm }; map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions); marker = new google.maps.Marker({ map:map, draggable:true, animation: google.maps.Animation.DROP, position: parliament }); google.maps.event.addListener(marker, 'click', toggleBounce); } function toggleBounce() { if (marker.getAnimation() != null) { marker.setAnimation(null); } else { marker.setAnimation(google.maps.Animation.BOUNCE); } }
查看示例 (marker-animations.html)
注意:如果您有多个Marker,则不应让所有Marker同时掉落到地图上。您可以调用 setTimeout()方法,(类似于以下示例中所示)来间隔显示标记的动画效果。
查看示例 (marker-animations-iteration.html)
3.2自定义Marker
Marker也可以定义为图标(icon)来替代原默认的Google图钉形状。定义icon涉及到一系列关于Marker外观的属性设置。
3.2.1简单图标(Icon)
在绝大多数情况下,可以通过设置Marker的icon属性为某一图像的URL地址的方法,来替换掉默认的Google图钉图标。
在下面的例子中,创建了一个icon标示澳大利亚Bondi海滩的位置。
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-simple.html)
3.2.2 复杂Icon
复杂Icon可用于指定复杂的形状(表示用户可点击的区域)、添加阴影,以及指定这些形状与其他叠加层在显示时的“压盖顺序”。以这种方式设定的Icon需要将Marker的 icon 属性和 shadow 属性设置为 MarkerImage 类型的对象。
阴影通常应该和主图像成 45 度夹角(向右上方倾斜),并且阴影的左下角应与图标图像的左下角对齐。阴影图像应是半透明的 24 位 PNG 图像,这样图像边界便可以在地图上正确显示。
MarkerImage 对象不仅可以定义显示的图像,还可以定义图标的大小、图标的原点(比如,您所需要的图像只是一幅较大图像的一部分。)以及图标所定位的热点对应的 anchor属性(基于原点距离)。
以下示例介绍了如何创建复杂的Icon,来表示澳大利亚新南威尔士悉尼附近的海滩。请注意,应当将 anchor 设置为 (0,32),从而与旗杆的基座相对应。
function initialize() { var mapOptions = { 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"), mapOptions); setMarkers(map, beaches); } /** * Marker包括的数据项分别为名称,经纬度,以及zIndex(标示彼此压盖顺序) */ 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) { // 将Marker添加到地图上 // Marker的大小用X,Y表示 // 图像(0,0)表示的是图像的左上角 // Origins, anchor的坐标都是横轴向右增加,纵轴向下增加 var image = new google.maps.MarkerImage('images/beachflag.png', // 该marker 20个像素宽,32个像素高 new google.maps.Size(20, 32), // 图像原点0,0. new google.maps.Point(0,0), // 图像anchor属性为(0,32) new google.maps.Point(0, 32)); var shadow = new google.maps.MarkerImage('images/beachflag_shadow.png', // 阴影在横轴方向宽 // 高和主图像相同 new google.maps.Size(37, 32), new google.maps.Point(0,0), new google.maps.Point(0, 32)); // shape定义了图标可点击的区域 // 该类型是一系列x,y坐标串。最后一个坐标和第一个坐标自动闭合。 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] }); } }
查看示例 (icon-complex.html)
3.2.3 矢量Icon
Marker既支持栅格图像也支持矢量路径(也称之为Symbol)。为了显示矢量路径(path),需要将Maker的Icon属性设置成一个Symbol对象。您可以使用google.maps.SymbolPath内置的path,也可以通过SVG Path语法规则自定义Path。
更多关于Google maps矢量图形信息,参见symbol的相关文档。
下面示例展示的通过内置的矢量path创建一个icon。详细的示例,参见Symbol一节。
marker = new google.maps.Marker({ position: new google.maps.LatLng(-25.363882, 131.044922), icon: { path: google.maps.SymbolPath.CIRCLE, scale: 10 }, draggable: true, map: map });
4 折线(Polyline)
Polyline 类定义地图上线段彼此相连的折线。Polyline 对象包含一组经纬度位置,由此创建了一系列按顺序相连的线段。
4.1 折线选项(Polyline Options)
Polyline 构造函数通过Polyline Options对象来指定线的经纬度坐标,以及线的外观。
Polyline 就是在地图上绘制的一系列直线段。您可以在构造Polyline时,通过 Polyline options 对象指定线的画笔颜色、粗细和透明度,或者在构造之后更改这些属性。Polyline支持以下画笔样式:
- strokeColor 指定 "#FFFFFF" 格式的十六进制 HTML 颜色。Polyline 类不支持颜色名称。
- strokeOpacity 指定线的颜色不透明度,为 0.0 到 1.0(默认值)之间的小数值。
- strokeWeight 指定线的粗细(以像素为单位)。
除此之外,Polyline的editable属性定义的是该形状是否允许用户在地图上编辑。
以下代码段绘制一条粗细为 2 像素的红色折线,连接威廉·金斯福德·史密斯 (William Kingsford Smith) 从美国加利福尼亚州奥克兰到澳大利亚布里斯班的首次跨太平洋飞行路线。
function initialize() { var myLatLng = new google.maps.LatLng(0, -180); var myOptions = { zoom: 3, center: myLatLng, mapTypeId: google.maps.MapTypeId.TERRAIN }; var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); var flightPlanCoordinates = [ new google.maps.LatLng(37.772323, -122.214897), new google.maps.LatLng(21.291982, -157.821856), new google.maps.LatLng(-18.142599, 178.431), new google.maps.LatLng(-27.46758, 153.027892) ]; var flightPath = new google.maps.Polyline({ path: flightPlanCoordinates, strokeColor: "#FF0000", strokeOpacity: 1.0, strokeWeight: 2 }); flightPath.setMap(map); }
4.2 Polyline数组
Polyline通过Latlng对象数组来设定一系列坐标。要访问这些坐标,需要调用Polyline的GetPath方法,它会传回MVCArray类型的数组。并且可以使用以下方法来操作和检查数组:
- getAt() 用于在指定的索引值(从零开始)处传回 LatLng值。
- insertAt() 用于在指定索引值(从零开始)处插入所传递的 LatLng值。注意,由于插入操作,使得所有在索引值之后坐标均向后移动。
- removeAt() 用于在指定的索引值(从零开始)处删除 LatLng值。
注意:不能只是使用语法 mvcArray[i] 检索数组的第 i 个元素,而必须使用 mvcArray.getAt(i)。
以下代码创建了一幅交互式地图,其中的折线是根据用户的点击构造的。请注意,只有当折线的 path 属性包含两个 LatLng 坐标时,折线才会显示。
var poly; var map; function initialize() { var chicago = new google.maps.LatLng(41.879535, -87.624333); var myOptions = { zoom: 7, center: chicago, mapTypeId: google.maps.MapTypeId.ROADMAP }; map = new google.maps.Map(document.getElementById('map_canvas'), myOptions); var polyOptions = { strokeColor: '#000000', strokeOpacity: 1.0, strokeWeight: 3 } poly = new google.maps.Polyline(polyOptions); poly.setMap(map); //对”click”事件添加监听器 google.maps.event.addListener(map, 'click', addLatLng); } /** * 处理地图上单击事件,并且为Polyline添加新的点。 * @param {MouseEvent} mouseEvent */ function addLatLng(event) { var path = poly.getPath(); // 由于path是MVCArray类型, 我们只是简单添加新的坐标, // 并且Path将自动显示 path.push(event.latLng); // 在Polyline上新增的点上再增加一个Marker var marker = new google.maps.Marker({ position: event.latLng, title: '#' + path.getLength(), map: map }); }
查看示例 (polyline-complex.html)
4.3 Polyline符号化
您可以对Polyline进行符号化。为了对Polyline符号化,需要设置PolylineOptions对象的icons[]属性。Icons数组中会有一个或者多个IconSequence序列,IconSequence包含如下几项:
- icon(必须的),线符号。关于如何对线进行符号化参见Symbols一节。
- offset从线顶端开始需要符号化的距离。该距离可以表示为线长的百分比(如50%)或者象素(如“50px”),默认为“100%”。
- repeat表示线上符号之间的距离。该距离可以表示为线长度的百分比(如50%)或者象素(如“50px”)。为了符号不重复,可以将该值设置为“0”。默认为 “0”。
如果Polyline是具有地理坐标的一条线,那么offset和repeat距离的默认单位应该是米。将offset或者repeat设置为象素值,那么Google会自动计算该距离在屏幕上的象素值。
通过对符号的组合,以及使用PolylineOptions类,您还可以对地图上的线外观有更多的控制。下面是几个典型的例子。
箭头
使用IconSequence.offset属性,可以为线的两端天价箭头。在这个例子中将offset设置为100%,这样把箭头就放置在线的末端。
var lineCoordinates = [ new google.maps.LatLng(22.291, 153.027), new google.maps.LatLng(18.291, 153.027) ]; var lineSymbol = { path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW }; var line = new google.maps.Polyline({ path: lineCoordinates, icons: [{ icon: lineSymbol, offset: '100%' }], map: map });
虚线
您可以先将Polyline的透明度设置为0%,然后每隔固定间隔绘制不透明的符号来达到虚线的效果。
var lineCoordinates = [ new google.maps.LatLng(22.291, 153.027), new google.maps.LatLng(18.291, 153.027) ]; var lineSymbol = { path: 'M 0,-1 0,1', strokeOpacity: 1, scale: 4 }; var line = new google.maps.Polyline({ path: lineCoordinates, strokeOpacity: 0, icons: [{ icon: lineSymbol, offset: '0', repeat: '20px' }], map: map });
自定义路径
自定义符号允许您在Polyline上添加多个不同的形状。
var lineCoordinates = [ new google.maps.LatLng(22.291, 153.027), new google.maps.LatLng(18.291, 153.027) ]; var symbolOne = { path: 'M -2,0 0,-2 2,0 0,2 z', strokeColor: '#F00', fillColor: '#F00', fillOpacity: 1 }; var symbolTwo = { path: 'M -2,-2 2,2 M 2,-2 -2,2', strokeColor: '#292', strokeWeight: 4 }; var symbolThree = { path: 'M -1,0 A 1,1 0 0 0 -3,0 1,1 0 0 0 -1,0M 1,0 A 1,1 0 0 0 3,0 1,1 0 0 0 1,0M -3,3 Q 0,5 3,3', strokeColor: '#00F', rotation: 0 }; var line = new google.maps.Polyline({ path: lineCoordinates, icons: [{ icon: symbolOne, offset: '0%' },{ icon: symbolTwo, offset: '50%' },{ icon: symbolThree, offset: '100%' } ], map: map });
动画符号
可以通过setTimeout()函数在固定时间间隔内改变符号的偏移量,从而使得符号似乎沿某一路径在运动。
var line; function initialize() { var mapOptions = { center: new google.maps.LatLng(20.291, 153.027), zoom: 6, mapTypeId: google.maps.MapTypeId.ROADMAP }; var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions); var lineCoordinates = [ new google.maps.LatLng(22.291, 153.027), new google.maps.LatLng(18.291, 153.027) ]; var lineSymbol = { path: google.maps.SymbolPath.CIRCLE, scale: 8, strokeColor: '#393' }; line = new google.maps.Polyline({ path: lineCoordinates, icons: [{ icon: lineSymbol, offset: '100%' }], map: map }); } function animateCircle() { var count = 0; offsetId = window.setInterval(function() { count = (count + 1) % 200; var icons = line.get('icons'); icons[0].offset = (count / 2) + '%'; line.set('icons', icons); }, 20); }
5 多边形(Polygon)
Polygon 对象类似于 Polyline 对象,都由一系列有序坐标构成。不过,多边形不像折线一样有两个端点,而是定义闭合区域。与折线类似的是,您可以定义影响多边形轮廓的画笔;不同的是,您还可以定义多边形内的填充区域。
此外,Polygon 还可以展示复杂形状,包括不连续形状(多个多边形定义为一个多边形)、“圆环”(多边形区域在多边形内显示为“岛”)以及一个或多个多边形的交叉重叠。因此,一个多边形可指定多条路径(Path)。
5.1 多边形选项(Polygon Options)
与Polyline一样,您可以定义Polygon的边(“画笔”)的自定义颜色、粗细和不透明度,以及封闭区域(“填充”)的自定义颜色和不透明度。颜色应当采用十六进制数字的HTML样式。
由于Polygon区域可能包括多条独立的Path,因此 Polygon 对象的 paths 属性指定成“数组的数组”(每个都是 MVCArray 类型),其中每个数组分别定义一系列 LatLng 有序坐标。
但是,对于只包含一条Path的简单Polygon,为方便起见,您可以采用单个 LatLng 坐标数组构造 Polygon。在将数组存储到 Polygon 的 paths 属性时,Google Maps API 会在构造时将其转换为“数组的数组”。同样,该API还为只包含一条Path的简单多边形提供了简单的 getPath() 方法。
注意:如果采用此方式构造Polygon,则仍需要将路径处理为 MVCArray,以便检索多边形的值。
除此之外, Polygon的editable值规定了地图上的Polygon是否可编辑。
以下代码段创建一个表示百慕大三角的多边形:
function initialize() { var myLatLng = new google.maps.LatLng(24.886436490787712, -70.2685546875); var mapOptions = { zoom: 5, center: myLatLng, mapTypeId: google.maps.MapTypeId.TERRAIN }; var bermudaTriangle; var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions); var triangleCoords = [ new google.maps.LatLng(25.774252, -80.190262), new google.maps.LatLng(18.466465, -66.118292), new google.maps.LatLng(32.321384, -64.75737), new google.maps.LatLng(25.774252, -80.190262) ]; // Construct the polygon // Note that we don't specify an array or arrays, but instead just // a simple array of LatLngs in the paths property bermudaTriangle = new google.maps.Polygon({ paths: triangleCoords, strokeColor: "#FF0000", strokeOpacity: 0.8, strokeWeight: 2, fillColor: "#FF0000", fillOpacity: 0.35 }); bermudaTriangle.setMap(map); }
5.2 多边形自动闭合
上例中的 Polygon 包含四个坐标,但第一个坐标和最后一个坐标为相同位置,从而定义了一个环路。不过,实际上由于多边形定义的就是封闭区域,因而无需定义这最后一个坐标。
对于任意指定路径,Google Maps API 将通过绘制连接最后一个坐标和第一个坐标以自动“封闭”任何多边形。
下例除了省略最后一个坐标之外,其他与上例均相同。
5.3 Polygon数组
多边形将其一系列坐标指定为数组的数组,其中每个数组都是 MVCArray 类型。每个子数组都是 LatLng 坐标的数组,用于指定单条Path。要检索这些坐标,可调用 Polygon 的getPaths() 方法。由于数组为 MVCArray,因此您需要使用以下操作处理和检查该数组:
- getAt() 用于在指定的索引值(从零开始)处传回 LatLng。
- insertAt() 用于在指定索引值(从零开始)处插入所传递的 LatLng。注意,该索引值的所有现有坐标均向前移动。
- removeAt() 用于在指定的索引值(从零开始)处删除 LatLng。
注意:不能只是使用语法 mvcArray[i] 检索数组的第 i 个元素,而必须使用 mvcArray.getAt(i)。
以下代码通过显示Polygon的坐标信息,处理Polygon的点击事件:
var map; var infoWindow; function initialize() { var myLatLng = new google.maps.LatLng(24.886436490787712, -70.2685546875); var myOptions = { zoom: 5, center: myLatLng, mapTypeId: google.maps.MapTypeId.TERRAIN }; var bermudaTriangle; map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); var triangleCoords = [ new google.maps.LatLng(25.774252, -80.190262), new google.maps.LatLng(18.466465, -66.118292), new google.maps.LatLng(32.321384, -64.75737) ]; bermudaTriangle = new google.maps.Polygon({ paths: triangleCoords, strokeColor: "#FF0000", strokeOpacity: 0.8, strokeWeight: 3, fillColor: "#FF0000", fillOpacity: 0.35 }); bermudaTriangle.setMap(map); // 为click事件添加监听器 google.maps.event.addListener(bermudaTriangle, 'click', showArrays); infowindow = new google.maps.InfoWindow(); } function showArrays(event) { // 因为该Polygon只有一个path,因此调用getpath()方法返回 // LatLngs的MVCArray数组。 var vertices = this.getPath(); var contentString = "<b>Bermuda Triangle Polygon</b><br />"; contentString += "Clicked Location: <br />" + event.latLng.lat() + "," + event.latLng.lng() + "<br />"; // 对顶点进行循环 for (var i =0; i < vertices.length; i++) { var xy = vertices.getAt(i); contentString += "<br />" + "Coordinate: " + i + "<br />" + xy.lat() +"," + xy.lng(); } // 替换掉Infowindow的内容,以及修改其位置 infowindow.setContent(contentString); infowindow.setPosition(event.latLng); infowindow.open(map); }
6 圆形(Circle)和矩形(Rectangle)
除了普通的 Polygon 类之外,JavaScript Maps API 还包括面向 Circle 和 Rectangle 的特定类,简化Polygon的构造。
6.1 Circle
Circle 与 Polygon 类似,您可以自定义Cirlce(“画笔”)边缘的颜色、粗细和透明度,以及封闭区域(“填充”)的颜色和透明度。颜色应当采用十六进制数字的 HTML 样式。
与 Polygon 不同,您不应为 Circle 定义 paths;圆形有两个用于定义其形状的其他属性:
- center 用于指定圆心,类型为google.maps.LatLng;
- radius 用于指定该圆的半径(以米为单位)。
除此之外,Circle的editable属性规定了图形在地图上是否可编辑。
下列代码段创建了用于表示美国人口的圆形:
// 创建一个对象包含经纬度和对应人口 var citymap = {}; citymap['chicago'] = { center: new google.maps.LatLng(41.878113, -87.629798), population: 2842518 }; citymap['newyork'] = { center: new google.maps.LatLng(40.714352, -74.005973), population: 8143197 }; citymap['losangeles'] = { center: new google.maps.LatLng(34.052234, -118.243684), population: 3844829 } var cityCircle; function initialize() { var mapOptions = { zoom: 4, center: new google.maps.LatLng(37.09024, -95.712891), mapTypeId: google.maps.MapTypeId.TERRAIN }; var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions); for (var city in citymap) { // 构建圆形大小 var populationOptions = { strokeColor: "#FF0000", strokeOpacity: 0.8, strokeWeight: 2, fillColor: "#FF0000", fillOpacity: 0.35, map: map, center: citymap[city].center, radius: citymap[city].population / 20 }; cityCircle = new google.maps.Circle(populationOptions); } }
查看示例(Circle-simple.html)
6.2 Rectangle
Rectangle 与 Polygon 类似,您可以自定义矩形(“画笔”)边缘的颜色、粗细和透明度,以及封闭区域(“填充”)的颜色和透明度。颜色应当采用十六进制数字的 HTML 样式。
与 Polygon 不同,您不应为 Rectangle 定义 path;矩形有一个用于定义其形状的其他属性:
- bounds 用于指定矩形的边界,类型为 google.maps.LatLngBounds。
除此之外,Rectangle的editable属性规定了图形在地图上是否可编辑。
以下示例会在任何 'zoom_changed' 事件发生时基于前一个视口创建矩形:
7. 用户可编辑的形状
任何一个图形Overlay(折线,多边形,圆和矩形)都可通过将Shape选项中的editable属性设置为true,变成“可编辑”的。
为了使marker可拖拽,需要将maker option中的draggable属性设置为true。
var circleOptions = { center: new google.maps.LatLng(-34.397, 150.644), radius: 25000, map: map, editable: true }; var circle = new google.maps.Circle(circleOptions);
查看示例(user-editable-shape.html例子)
在两个会话间,对几何对象所做的修改是无法保存的。如果您需要保存对Polygon的修改,那么您必须自己保存这些信息。
7.1编辑事件
当一个图形被编辑时,编辑完成后会触发编辑事件,如下所示:
图形 |
事件 |
Circle |
radius_changed center_changed |
Polygon |
insert_at remove_at set_at 必须在Polygon的Path上设置事件的监听器,如果Polygon有多个path,那么必须在各个path上设置监听器。 |
Rectangle |
bounds_changed |
google.maps.event.addListener(circle, 'radius_changed', function() { radius = circle.getRadius(); }); google.maps.event.addListener(outerPath, 'set_at', function() { print('Vertex moved on outer path.'); }); google.maps.event.addListener(innerPath, 'insert_at', function() { print('Vertex removed from inner path.'); });
8. 绘图(Drawing)库
在这篇文档中绘图库的概念是指google.maps.drawing库。默认情况下,当加载地图Javascritp API时,该库不会被加载,必须通过“libraries”指令显式指定才能加载。
http://maps.googleapis.com/maps/api/js?sensor=false&libraries=drawing
更多相关信息参见 Libraries in the V3 Maps API
DrawingManager类提供了一个绘图接口,供用户在地图上绘制多边形、矩形、折线、圆以及Marker。下面是创建一个DrawingManager对象。
var drawingManager = new google.maps.drawing.DrawingManager(); drawingManager.setMap(map);
8.1 DrawingManager选项
DrawingManager构造函数接受一组选项参数,来定义控件的显示外观,位置以及初始绘制状态。
- DrawingManager类的drawingMode属性定义了DrawingManager的初始绘制状态。它接受一个google.maps.drawing.OverlayType常量。默认值为null,当DrawingManager初始化时,光标为非绘制状态。
- DrawingManager类的drawingControl属性定义了地图上绘制工具是否可见。它接受boolean类型的值。
- 您也可以定义控件的位置,使用DrawingManager类的drawingControlOptions选项定义在控件上显示几种类型的overlay。
- position定义地图上绘图控件的位置,它接受google.maps.ControlPosition常量。
- drawingModes是一个google.maps.drawing.OverlayType常量的数组,定义了包含多少个Overlay图形绘制的工具。“手形”图标总是存在,允许用户在不绘制的情况下和地图交互。工具出现的顺序和它们在数组中的顺序一致。
- 每种类型的Overlay都有默认的属性。这些属性定义了Overlay创建时的外观。这些属性都在Overlay的{Overlayer}Options属性中。({Overlay}代表了Overlay的类型)。举例来说,Circle的填充,画笔,zIndex以及是否可单击等属性都在CircleOptions当中定义。如果传入了大小、位置或者拥有该Overlay的Map值,那么CircleOptions中的值将被忽略。关于这些属性更多的细节,参见API Reference documentation。
为了图形被创建后可编辑,需要将editable设置为true。
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, google.maps.drawing.OverlayType.POLYGON, google.maps.drawing.OverlayType.POLYLINE, google.maps.drawing.OverlayType.RECTANGLE ] }, 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);
查看示例 (drawing-tools.html)
8.2 图形绘制工具控件(Drawing Tools)更新
DrawingManager对象被创建后,您可以通过调用SetOptions方法传入参数来更新该控件。
drawingManager.setOptions({
drawingControlOptions: {
position: google.maps.ControlPosition.BOTTOM_LEFT,
drawingModes: [google.maps.drawing.OverlayType.MARKER]
}
})
隐藏或者显示drawing tools控件。
// 隐藏: drawingManager.setOptions({ drawingControl: false }); // 显示: drawingManager.setOptions({ drawingControl: true });
在map对象上移除绘图控件。
drawingManager.setMap(null);
隐藏绘图控件会使得该控件不显示,但是DrawingManager类的功能依然可用。如果需要,您可以按照此方式实现自己的控件。从map对象上移除DrawingManager类,则会移除所有绘图功能。如果所有绘制要素要重置的话,那么DrawingManager类通过drawingManager.setMap(map)或者构造新的DrawingManager对象来和地图重新关联。
Drawing事件
当一个图形Overlay被创建时,有两个事件会被激发:
- 一个是{Overlay}complete事件({overlay}代表了overlay的类型,比如circlecomplete,polycomplete事件等)。overlay的句柄作为参数传入。
- 一个是overlaycomplete事件。一个对象数组,包含OverlayType以及overlay的句柄。
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(); } });
9.信息窗口(InfoWindow)
InfoWindow 在地图上方的浮动窗口中显示内容。信息窗口有点像漫画书上的文字气球,它有一个内容区域和锥形引线,引线的头位于地图的指定位置上。通过点击 Google Maps 上的商户标记,您可以看到活动的信息窗口。
InfoWindow 构造函数采用的是 InfoWindow options 对象,该对象指定了用于显示信息窗口的一组初始参数。在创建信息窗口的过程中,系统不会在地图上添加信息窗口。要显示信息窗口,您需要调用 InfoWindow 上的 open() 方法,向其传递要在其中打开信息窗口的 Map,以及向其传递用于锚定信息窗口的 Marker(可选)。(如果未提供任何标记,那么,会在其 position 属性上打开信息窗口)。
InfoWindow options 对象是包含以下字段的对象常量:
- content 包含了信息窗口打开时,系统要在其中显示的文本字符串或 DOM 节点。
- pixelOffset 包含了从信息窗口的顶部到信息窗口锚定位置的偏移量。实际上,您不应也无需修改此字段。
- position 包含了此信息窗口锚定位置的 LatLng。请注意,在标记上执行打开信息窗口操作时,系统会自动使用一个新位置更新该值。
- maxWidth 指定了信息窗口的最大宽度(以像素为单位)。默认情况下,信息窗口会根据其中包含的内容进行扩展,如果信息窗口随着地图的大小而扩展,那么,文本将会自动换行。如果您应用了 maxWidth,那么,信息窗口将自动换行以强制适应像素的宽度。如果屏幕的实际使用面积允许的话,信息窗口在达到最大宽度后仍可垂直扩展。
InfoWindow 的内容可以是文本字符串、HTML 代码段或 DOM 元素本身。要设置此内容,请在 InfoWindow options 构造函数中传递该内容,或者对InfoWindow显式调用 setContent()。如果想要显式调整内容的大小,您可以使用 <div> 进行此操作,如果您愿意,还可以启用滚动功能。请注意,如果您没有启用滚动功能,而内容的大小又超过了信息窗口的可用空间,那么,内容可能会从信息窗口中“溢”出。
InfoWindow 可附加到 Marker 对象(在这种情况下,它们的位置取决于标记的位置)上,或附加到地图本身指定的 LatLng 位置上。如果您一次只想显示一个信息窗口(正如 Google Maps 上的相应行为),那么,您只需创建一个信息窗口,然后在地图事件(例如用户点击)执行过程中将此信息窗口重新分配到不同的位置或标记中。但与 Google Maps API 第 2 版中的相应行为不同的是,如果您选择进行上述操作,那么,地图可能会立即显示多个 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); });
查看示例 (infowindow-simple.html)
以下显示了将信息窗口 maxWidth 设置为 200 像素的示例:
查看示例 (infowindow-simple-max.html)
10. Ground Overlay
多边形可以表示任意不规则的区域,但是它们无法显示图像。如果您有图像希望显示在地图上,那么需要用到GroundOverlay对象。GroundOverlay的构造函数中需要指定图像的URL以及图像的边界(LatLngBounds)。该图像将显示在地图上,并且限制在指定的边界里,同时使用当前地图的投影。
下面的例子是将新泽西州的纽瓦克古地图作为一个Overlay叠加到地图上。
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);
查看示例(groundoverlay-simple.html)
11. 自定义Overlay
Google Maps API 第 3 版提供了用于创建自定义叠加层的 OverlayView 类。OverlayView 是一个基类,提供了您在创建Overlay时必须实现的若干方法。该类还提供了一些方法,用于实现屏幕坐标和地图位置之间的转换。
要创建自定义叠加层,请执行以下操作:
- 将自定义对象的 prototype 设置为 google.maps.OverlayView() 的新实例。这可以有效地实现叠加层类的“子类化”。
- 为自定义叠加层创建构造函数,并将该构造函数中的所有初始化参数都设置为自定义属性。
- 在原型中实现 onAdd() 方法,以将叠加层附加到地图上。当地图准备好附加叠加层后,系统将会调用 OverlayView.onAdd()。
- 在原型中实现 draw() 方法,以处理对象的视觉显示。同样,在对象首次显示后,系统将会调用 OverlayView.draw()。
- 您还应当实现 onRemove() 方法,以清理在叠加层中添加的所有元素。
我们将会在以下各部分中逐步介绍这些操作。
11.1 Overlay的子类化
我们将会使用 OverlayView 创建简单的图像叠加层(与第 2 版 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); //美国地质调查局影像 var srcImage = 'images/talkeetna.png'; overlay = new USGSOverlay(bounds, srcImage, map); }
接下来,我们则会创建该类的一个构造函数,并将已传递的参数初始化为新对象的属性。此外,我们还需要显式地将 USGSOverlay 中的 OverlayView 子类化。我们可通过将新类的 prototype 设置为父类的一个实例进行上述操作(由于我们不希望修改父类,因此,我们在此处将prototype设置为父类实例,而非父类本身)。
function USGSOverlay(bounds, image, map) { //初始化所有属性. this.bounds_ = bounds; this.image_ = image; this.map_ = map; // 定义一个能存储影像的Div.在add() // 方法里创建该div,现在将其设为null值 this.div_ = null; // 显式调用setMap方法 this.setMap(map); } USGSOverlay.prototype = new google.maps.OverlayView();
10.2 初始化Overlay
当Overlay第一次创建并处于准备显示状态时,我们需要通过浏览器的 DOM模型将Overlay和地图连接起来。当Overlay添加到地图上时,会调用overlay的onAdd()方法。在这个方法中,我们会创建一个<div>来保存我们的图像,并且
在处理此方法时,我们会创建一个用于保存图像的 <div>,添加一个 <img> 元素,将该元素附加到 <div>,最后将叠加层附加到地图的一个“窗格”(即 DOM 树中的节点)中。
一组 MapPanes 类型的窗格用于指定不同的层在地图上的堆叠顺序。您可以使用以下窗格,并且可以按照由下至上的堆叠顺序枚举这些窗格。
- MapPanes.mapPane
- MapPanes.overlayLayer
- MapPanes.overlayShadow
- MapPanes.overlayImage
- MapPanes.floatShadow
- MapPanes.overlayMouseTarget
- MapPanes.floatPane
由于我们的图像为“ground overlay”,因此,我们将会使用 overlayLayer 地图窗格。创建了此窗格后,我们会以子对象的形式将对象附加到窗格上。
USGSOverlay.prototype.onAdd = function() { // 注意:overlay的onAdd()方法表明地图的 // pane可以通过DOM模型将overlay和map关联起来 // 创建一个Div,并且设置若干基础属性 var div = document.createElement('div'); div.style.border = "none"; div.style.borderWidth = "0px"; div.style.position = "absolute"; // 创建img标签,并将img和div联系起来 var img = document.createElement("img"); img.src = this.image_; img.style.width = "100%"; img.style.height = "100%"; div.appendChild(img); // 将overlay的div和该div关联起来 this.div_ = div; // 通过map的pane将overlay和map关联起来 // 将overlay添加到overlayimage pane上 var panes = this.getPanes(); panes.overlayLayer.appendChild(div); }
11.3 Overlay绘制
请注意,在上述操作中,我们实际上并未调用任何特殊的视觉显示。每当需要在地图上绘制叠加层时(其中包括首次添加叠加层时),API 都会对叠加层调用独立的 draw() 方法。
因此,我们将会实现此 draw() 方法,然后使用 getProjection() 检索overlay的 MapCanvasProjection,并计算对象的右上角和左下角锚定点的准确坐标,以此重新调整 <div> 的大小;反之,此操作又可重新调整图像的大小,从而让图像与我们在overlay的构造函数中所指定的范围相匹配。
USGSOverlay.prototype.draw = function() { // 调整overlay的尺寸和位置。我们使用overlay的西南和东北 // 两点来调整overlay正确的位置和尺寸。我们需要从overlay // 获得投影来完成 var overlayProjection = this.getProjection(); // 获得overlay的西南和东北坐标(latlngs),然后将其转换为 // 屏幕像素坐标。我们使用该坐标来调整Div。 var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest()); var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast()); // 调整图像的Div来满足所指定的坐标 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'; }
11.4 删除Overlay
我们还会添加 onRemove() 方法,完全删除地图中的叠加层。如果我们曾经将叠加层的 map 属性设置为 null,那么,系统将会自动通过 API 调用此方法。
USGSOverlay.prototype.onRemove = function() { this.div_.parentNode.removeChild(this.div_); this.div_ = null; }
查看示例(overlay-simple.html)
11.5 隐藏和显示overlay
如果您想要隐藏或显示overlay,而不只是创建或删除overlay,您可以实现 hide() 和 show() 方法,以调整overlay的可见性。或者,您也可以将overlay与地图的 DOM 分离,但这种操作的成本有些过高。请注意,如果您随后将叠加层重新附加到地图的 DOM 上,则系统会重新调用叠加层的 onAdd()方法。
以下示例介绍了如何将 hide() 和 show() 方法添加到overlay的原型中,这样可以切换显示容器 <div>。此外,我们还添加了 toogleDOM() 方法,它可将overlay附加到地图,或者将两者分离开来。请注意,如果我们将visibility设置为 "hidden",然后通过 toggleDOM() 将地图与 DOM 分离,随后又重新附加了地图,那么,叠加层会再次显示出来,这是因为,我们在叠加层的 onAdd() 方法中重新创建了其中所包含的 <div>。
// 注意visibility属性必须是个字符串 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_); } }
// 现在添加一个按钮来触发该事件 <div id ="toolbar" width="100%; height:20px;" style="text-align:center"> <input type="button" value="Toggle Visibility" onclick="overlay.toggle();"></input> <input type="button" value="Toggle DOM Attachment" onclick="overlay.toggleDOM();"></input> </div> <div id="map_canvas" style="width: 100%; height: 95%;"></div>