GIS的积累
It is never to late to learn

导航

 

http://www.360doc.com/content/07/0604/09/18472_537334.shtml 好的参考网站,例子比较好的。

 来源: Google官网:http://www.google.com/intl/zh-CN/apis/maps/documentation/        时间:2008-01-04

      Google 地图 JavaScript API 使您能够将 Google 地图嵌入到自己的网页中。在使用该 API 之前,您需要先申请一个 API Key,然后按照如下的指南操作。
    由于 API 比较新,其中有可能存在一些不足,另外文档也还不够完美。请您多多包涵,我们会不断进行改进。同时,欢迎您加入
地图 API 讨论组给我们反馈,并且讨论关于 API 的问题。

   文档是根据英文版的 Google Maps API 版本 2 编写的。  有关英文版 Google Maps API 2 的最新功能,请参见 英文版 Google Maps API 第 2 版文档
   请注意,为了使用中国的地图数据,您需要使用来自
ditu.google.com 的 JavaScript 代码。 申请 API Key 时自动生成的代码缺省指向 maps.google.com。因此,您需要手动将其改为 ditu.google.com。另外, Google Maps API 2 的某些功能目前还不支持中国。
     关于 Google 地图 API,请您在
Google 地图 API 讨论组讨论交流。如果参与英文 Maps API 讨论组,请说明您使用的是中文版 Google 地图 API,以避免误解。

目录

面向的读者

本文档适用于熟悉 JavaScript 以及面向对象编程概念的读者。另外,从用户的角度,您也应该很熟悉 Google 地图 这个产品。如果您遇到困难,网上有很多 JavaScript 指南 可供参考。

简介

您的第一个 Google 地图 程序:"Hello, World"

学习这个 API 最简单的方法就是从一个简单的例子开始。下面的网页显示一个 500x300 的地图,中心位于北京的故宫博物院

<!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 地图 JavaScript API 示例</title>
   
<script src="http://ditu.google.com/maps?file=api&amp;v=2&amp;key=abcdefg"
           
type="text/javascript"></script>
   
<script type="text/javascript">
   
//<![CDATA[

   
function load() {
     
if (GBrowserIsCompatible()) {
       
var map = new GMap2(document.getElementById("map"));
        map
.setCenter(new GLatLng(39.917, 116.397), 14);
     
}
   
}

   
//]]>
   
</script>
 
</head>
 
<body onload="load()" onunload="GUnload()">
   
<div id="map" style="width: 500px; height: 300px"></div>
 
</body>
</html>

您可以下载这个例子修改并测试,但是您必须用您自己的 API Key 代替文件中 Key。(如果您为某个目录注册了 API Key,那么该 API Key 也能够在它的任何子目录下使用)。

上面的例子中,地址 http://ditu.google.com/maps?file=api&v=2 包含了在您的页面放置 Google 地图所需要的所有 JavaScript 代码。您的页面必须包含指向这个地址的 script 标记,并加上您的 API Key。例如,如果您的 API Key 是"abcdefg",那么您的 script 标记应该类似这样:

<script src="http://ditu.google.com/maps?file=api&v=2&key=abcdefg"
       
type="text/javascript">
</script>

表示地图的类是 GMap2。这个类代表页面上的单个地图。您可以根据需要创建任意多个该类的实例(一个实例对应页面上的一个地图)。在创建地图实例时,您需要指定一个页面上已命名的元素(通常是 div 元素)作为地图控件的容器。除非您明确地指定了地图的大小,默认情况下,地图大小会取决于容器的尺寸。

浏览器兼容性

Google 地图 API 所支持的浏览器种类与 Google 地图网站相同。由于不同的应用程序在遇到不兼容的浏览器的时候需要采取不同的对策,所以地图 API 提供了一个全局方法(GBrowserIsCompatible())来检查兼容性。但是,当该方法发现一个不兼容的浏览器时,它不会自动采取任何措施。 http://ditu.google.com/maps?file=api&v=2 中的脚本几乎可以在任何浏览器中解析而不产生错误,所以您可以放心地在检查浏览器兼容性之前就包含该脚本文件。

除了上面的第一个例子以外,本文档中的其它例子都不会检查浏览器兼容性,也不会在老的浏览器中显示错误信息。当然,实际的应用程序应该在浏览器不兼容时采取一些用户友好的措施。但是,为了让范例代码易读,我们在本文中省略了这种检查。

不少应用程序都会不可避免地遇到浏览器或平台兼容性的问题。对于这类问题目前还没有简单的解决方案,但是您可以从 Google 地图 API 讨论组quirksmode.org 上找到一些解决技巧。

XHTML 和 VML

我们推荐您使用和标准兼容的 XHTML 页面来包含地图。当浏览器遇到页面顶端的 DOCTYPE,它们就会用"标准兼容模式"来呈现页面。这种模式下,页面的布局和行为在不同的浏览器间会具有更好的一致性。

如果您想在地图中显示折线,您需要在您的 XHTML 文档中包含 VML 命名空间和一些 CSS 代码。请注意:IE 浏览器需要它方能正常显示折线。XHTML 文档的开头应该类似这样:

<!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" xmlns:v="urn:schemas-microsoft-com:vml">
 
<head>
   
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
   
<title>我的 Google 地图</title>
   
<style type="text/css">
    v
\:* {
      behavior
:url(#default#VML);
   
}
   
</style>
   
<script src="http://ditu.google.com/maps?file=api&v=2&key=abcdefg"
             
type="text/javascript"></script>
 
</head>

API 版本更新

地址 http://ditu.google.com/maps?file=api&v=2 中的 v=2 部分表明您使用的 API 版本号是 2。您可以将它替换为 v=2.x 的形式,从而使用最新版本的 API。但是请注意,最新发布的版本可能并不如 v=2 所指向的版本那样稳定。我们大约每两周都会更新 Google 地图 API 的版本,届时 v=2.x 版本中的新功能就会作为稳定版本被替换到 v=2 所指向的版本中。

我们更新 API 版本时,都会给它们一个编号(例如,“版本 2.76”)。随着我们对 API 的更新,基于旧版本的 API 编写的代码偶尔可能会无法正常工作。如果您确实要限定您的程序所使用的 API 版本,您可以明确地将该版本号包含在 v 参数中(例如,v=2.75)。但是,我们不推荐这么做。如果可能,请尽量使您的产品适应更新的版本。

当我们对 API 进行重大升级时,我们会改变版本号并在 Google Code地图 API 讨论组 上发布相关信息。一个新版本正式发布以后,我们会让新旧版本至少同时运行一个月,从而使您有足够的时间将代码迁移到新的版本上。

另外,我们会以用户透明的方式更新 API 来解决 Bug 和提高性能。正常情况下,这些改动只会修正 Bug 或者提高性能,但是也可能会不经意地影响一些 API 用户的使用。如果您遇到问题,请到 地图 API 讨论组 来向我们反映。

地理译码 (Geocoding)

地理译码是把地址(如"1600 Amphitheatre Parkway, Mountain View, CA")转换为地理坐标(如经度-122.083739,纬度37.423021)的流程。通过它,您就可以把数据库中的街道地址或用户提供的地址信息标记在地图上。但是,到目前为止,中文 Google 地图 API 的地理译码器尚不支持地理译码。不过,您可以根据我们提供的规范开发自己的地理译码器,或者使用第三方提供的地理译码器。

行程规划和本地搜索

Google 地图 API 目前不包含行程规划服务。另外,Google 地图 API 目前尚不包含本地搜索服务。

标注管理

如果将太多的标注添加到地图中,可能会大大减慢地图的绘制。同时,大量堆积的标注也会影响地图的视觉效果,尤其是在那些较宏观的缩放级别上。为了解决上述问题,我们引入了"标注管理器"功能,它能够有效地将数以百计的标注添加到同一地图中,并指定哪些标注应该在哪些缩放级别上出现。

将标注添加到标注管理器后,管理器会自主地管理这些标注,根据当前的显示区域和缩放级别判断哪些标注是可见的,并只传送这些标注给地图进行绘制。标注管理器会监视当前地图的可见范围和缩放级别,动态地从地图上添加或删除标注。同时,由于允许给每个标注指定其可见的缩放级别,程序员能够很容易地实现类似“标注聚集”的功能。这种管理大大地提高了地图绘制的效率,并能有效避免视觉堆积。

示例程序

下面的例子都只包括相关的 JavaScript 代码片段,而不是完整的 HTML 文件。您可以把这些 JavaScript 代码嵌入到第一个例子中给出的 HTML 文件框架中。当然,您也可以直接点击每个例子下面的链接来下载完整的 HTML 文件。

基本操作

下面的例子创建一个地图,并把它的中心置于北京的故宫博物院

var map = new GMap2(document.getElementById("map"));
map
.setCenter(new GLatLng(39.917, 116.397), 14);

查看示例 (simple.html)

地图移动及动画

下面的例子先显示一个地图,等待 2 秒后,会将地图的中心移到一个新的坐标上。

panTo 方法将地图的中心移动到一个指定的点。如果指定的点之前位于地图的可见区域内,则地图会平滑地移动到那儿,否则,就直接跳转到那个点。

var map = new GMap2(document.getElementById("map"));
map
.setCenter(new GLatLng(39.917, 116.397), 14);
window
.setTimeout(function() {
  map
.panTo(new GLatLng(39.929419, 116.388302), 14);
}, 2000);

查看示例 (animate.html)

给地图添加控件

您可以用 addControl 方法在地图上添加控件。在这个例子里,我们加入 GSmallMapControlGScaleControl 控件,它们分别用于移动/缩放地图以及在地图上显示比例尺。

var map = new GMap2(document.getElementById("map"));
map
.addControl(new GSmallMapControl());
map
.addControl(new GScaleControl());
map
.setCenter(new GLatLng(39.917, 116.397), 14);

查看示例 (controls.html)

事件处理函数

可以用 GEvent.addListener 方法来注册事件处理函数。该方法接受三个参数:地图、要处理的事件、以及一个当事件发生时需要调用的函数。在下面的例子中,当用户缩放地图后,地图的缩放级别会显示在网页中。

var map = new GMap2(document.getElementById("map"));
map
.addControl(new GLargeMapControl());
GEvent.addListener(map, "zoomend", function() {
  document
.getElementById("message").innerHTML = map.getZoom();
});
map
.setCenter(new GLatLng(39.917, 116.397), 14);

查看示例 (event.html)

有关事件处理的更多信息,请参阅事件概览。要获得完整的 GMap2 所支持的事件列表,以及对应处理函数的参数,请参阅 GMap2.Events.

打开气泡提示窗口

要创建气泡提示窗口(信息窗口),可以调用 openInfoWindow 方法,并把要一个位置和一个要在其中显示的 DOM 元素作为参数传递给它。 下面的代码将在地图的中心显示一个信息窗口,其内容是“Hello, world”。

var map = new GMap2(document.getElementById("map"));
map
.setCenter(new GLatLng(39.917, 116.397), 14);
map
.openInfoWindow(map.getCenter(),
                   document
.createTextNode("Hello, world"));

查看示例 (infowindow.html)

地图覆盖物

这个例子会在地图上显示 10 个位置随机的标注和一个 5 个随机点连成的折线。如果不为标注指定图标,则 GMarker 类会使用缺省的 Google 地图图标。有关自定义图标的例子请参见创建图标

请记住:为了在 IE 中正常显示折线,必须在您的 HTML 文档中包含 VML 命空间和相关 CSS。更多信息请参见 XHTML 和 VML

var map = new GMap2(document.getElementById("map"));
map
.addControl(new GSmallMapControl());
map
.setCenter(new GLatLng(39.917, 116.397), 14);

// 随机地在地图上添加 10 个标注

var bounds = map.getBounds();
var southWest = bounds.getSouthWest();
var northEast = bounds.getNorthEast();
var lngSpan = northEast.lng() - southWest.lng();
var latSpan = northEast.lat() - southWest.lat();
for (var i = 0; i < 10; i++) {
 
var point = new GLatLng(southWest.lat() + latSpan * Math.random(),
                          southWest
.lng() + lngSpan * Math.random());
  map
.addOverlay(new GMarker(point));
}

// 添加一个由 5 个随机点连成的折线,把随机点按其经度排序以避免折线相交
var points = [];
for (var i = 0; i < 5; i++) {
  points
.push(new GLatLng(southWest.lat() + latSpan * Math.random(),
                          southWest
.lng() + lngSpan * Math.random()));
}
points
.sort(function(p1, p2) {
 
return p1.lng() - p2.lng();
});
map
.addOverlay(new GPolyline(points));

查看示例 (overlay.html)

单击事件处理

要在用户点击地图时触发一个动作,就需要给您的 GMap2 对象实例注册一个"click"事件的处理函数。当事件触发时,事件处理函数将收到两个参数:被点击的标注(如果有的话)、被点击点的经纬度坐标(GLatLng)。如果没有标注被点击,则第一个参数为 null

注意:标注是唯一支持"click"事件的内置覆盖物。而其它类型的覆盖物,如 GPolyline 是不能被点击的。

下面的例子中,当用户点击在地图上一个没有标注的位置时,我们就在这个位置创建一个标注;当用户点击在一个标注上时,我们就将它删除。

var map = new GMap2(document.getElementById("map"));
map
.addControl(new GSmallMapControl());
map
.addControl(new GOverviewMapControl());
map
.setCenter(new GLatLng(39.917, 116.397), 14);

GEvent.addListener(map, "click", function(marker, point) {
 
if (marker) {
    map
.removeOverlay(marker);
 
} else {
    map
.addOverlay(new GMarker(point));
 
}
});

查看示例 (click.html)

有关事件处理的更多信息,请参阅事件概览。要获得完整的 GMap2 所支持的事件列表,以及对应处理函数的参数,请参阅 GMap2.Events.

给标注增加气泡提示窗口

在这个例子中,我们捕获标注的单击事件,并为每个标注定制气泡提示窗口。利用 Javascript 函数闭包(匿名函数)技术,我们就可以为每个标注定制气泡提示窗口的内容。

var map = new GMap2(document.getElementById("map"));
map
.addControl(new GSmallMapControl());
map
.addControl(new GOverviewMapControl());
map
.setCenter(new GLatLng(39.917, 116.397), 14);

// 在给定的点上创建带编号的标注
function createMarker(point, number) {
 
var marker = new GMarker(point);
 
GEvent.addListener(marker, "click", function() {
    marker
.openInfoWindowHtml("标注 #<b>" + number + "</b>");
 
});
 
return marker;
}

// 在地图的随机位置添加 10 个标注
var bounds = map.getBounds();
var southWest = bounds.getSouthWest();
var northEast = bounds.getNorthEast();
var lngSpan = northEast.lng() - southWest.lng();
var latSpan = northEast.lat() - southWest.lat();
for (var i = 0; i < 10; i++) {
 
var point = new GLatLng(southWest.lat() + latSpan * Math.random(),
                          southWest
.lng() + lngSpan * Math.random());
  map
.addOverlay(createMarker(point, i + 1));
}

查看示例 (markerinfowindow.html)

有关事件处理的更多信息,请参阅事件概览。要获得完整的 GMap2 所支持的事件列表,以及对应处理函数的参数,请参阅 GMap2.Events.

多页的气泡提示窗口

第 2 版的 API 引入了 openInfoWindowTabs() 方法和 GInfoWindowTab 类,用于支持多页的气泡提示窗口。下面的例子演示了如何在标注上显示一个简单的多页气泡提示窗口。

var map = new GMap2(document.getElementById("map"));
map
.addControl(new GSmallMapControl());
map
.addControl(new GScaleControl());
map
.setCenter(new GLatLng(39.917, 116.397), 14);

// 气泡提示窗口的内容
var infoTabs = [
 
new GInfoWindowTab("页 #1", "这是第一页的内容"),
 
new GInfoWindowTab("页 #2", "这是第二页的内容")
];

// 将标注置于地图中央,并自动打开气泡提示窗口
var marker = new GMarker(map.getCenter());
GEvent.addListener(marker, "click", function() {
  marker
.openInfoWindowTabsHtml(infoTabs);
});
map
.addOverlay(marker);
marker
.openInfoWindowTabsHtml(infoTabs);

查看示例 (tabbedinfowindow.html)

创建图标

这个例子中,我们为标注自定义新的图标。创建新图标时,我们必须为它指定前景图片、阴影图片,以及图标相对于地图和气泡提示窗口的“锚点”。

var map = new GMap2(document.getElementById("map"));
map
.addControl(new GSmallMapControl());
map
.addControl(new GScaleControl());
map
.setCenter(new GLatLng(39.917, 116.397), 14);

// 创建我们的“缩微”图标
var icon = new GIcon();
icon
.image = "./images/mm_20_red.png";
icon
.shadow = "./images/mm_20_shadow.png";
icon
.iconSize = new GSize(12, 20);
icon
.shadowSize = new GSize(22, 20);
icon
.iconAnchor = new GPoint(6, 20);
icon
.infoWindowAnchor = new GPoint(5, 1);

// 在地图的随机位置添加 10 个标注
var bounds = map.getBounds();
var southWest = bounds.getSouthWest();
var northEast = bounds.getNorthEast();
var lngSpan = northEast.lng() - southWest.lng();
var latSpan = northEast.lat() - southWest.lat();
for (var i = 0; i < 10; i++) {
 
var point = new GLatLng(southWest.lat() + latSpan * Math.random(),
                          southWest
.lng() + lngSpan * Math.random());
  map
.addOverlay(new GMarker(point, icon));
}

查看示例 (icon.html)

使用图标类

通常,您需要创建一系列的图标,它们可能有很多不同的前景,但形状和背景却是相同的。此时最简单的方式就是利用 GIcon 类的复制构造函数,它会把现有图标的所有属性复制给您想定制的新图标。

var map = new GMap2(document.getElementById("map"));
map
.addControl(new GSmallMapControl());
map
.addControl(new GScaleControl());
map
.setCenter(new GLatLng(39.917, 116.397), 14);

// 为所有的标注创建一个“基准”图标,并指定它的阴影、尺寸、锚点等
var baseIcon = new GIcon();
baseIcon
.shadow = "http://ditu.google.com/mapfiles/shadow50.png";
baseIcon
.iconSize = new GSize(20, 34);
baseIcon
.shadowSize = new GSize(37, 34);
baseIcon
.iconAnchor = new GPoint(9, 34);
baseIcon
.infoWindowAnchor = new GPoint(9, 2);
baseIcon
.infoShadowAnchor = new GPoint(18, 25);

// 创建一个标注,它的气泡提示窗口会根据标注编号显示对应的英文字母
function createMarker(point, index) {
 
// 利用我们的图标类,为这个标注创建一个带字母的图标
 
var letter = String.fromCharCode("A".charCodeAt(0) + index);
 
var icon = new GIcon(baseIcon);
  icon
.image = "http://ditu.google.com/mapfiles/marker" + letter + ".png";
 
var marker = new GMarker(point, icon);

 
GEvent.addListener(marker, "click", function() {
    marker
.openInfoWindowHtml("标注 <b>" + letter + "</b>");
 
});
 
return marker;
}

// 在地图的随机位置添加 10 个标注
var bounds = map.getBounds();
var southWest = bounds.getSouthWest();
var northEast = bounds.getNorthEast();
var lngSpan = northEast.lng() - southWest.lng();
var latSpan = northEast.lat() - southWest.lat();
for (var i = 0; i < 10; i++) {
 
var point = new GLatLng(southWest.lat() + latSpan * Math.random(),
                          southWest
.lng() + lngSpan * Math.random());
  map
.addOverlay(createMarker(point, i));
}

查看示例 (iconclass.html)

可拖拽的标注

标注是支持用户交互的,您可以点击它,或将它拖动到一个新的位置。在这个例子中,我们在地图上放置一个可以拖动的标注,并捕获它的几个简单事件。可拖动的标注支持四种事件:clickdragstartdragdragend。标注默认是可以点击的,但不能被拖动。为此,我们必须在初始化标注时,为它指定一个附加的选项 draggable:true。缺省情况下,可拖动的标注在放下时会跳动。如果您不喜欢这个效果,可以把 bouncy 选项设置为 false

var map = new GMap2(document.getElementById("map"));
var center = new GLatLng(39.917, 116.397);
map
.setCenter(center, 14);

var marker = new GMarker(center, {draggable: true});

GEvent.addListener(marker, "dragstart", function() {
  map
.closeInfoWindow();
 
});

GEvent.addListener(marker, "dragend", function() {
  marker
.openInfoWindowHtml("标注放下时会跳动...");
 
});

map
.addOverlay(marker);

查看示例 (dragmarker.html)

编码折线

Google 地图中,GPolyline 对象是用一系列的点表示的,这种方法虽然简单易用但是不够简洁。当需要表示长且复杂的折线时会消耗大量的内存,而且绘制起来也很慢。此外,这种折线的每一条线段在地图的每个缩放级别中都可见,尽管在较低的分辨率下这是完全没有必要的。

鉴于此,Google 地图 API 也允许您用编码折线来表示路径。编码折线用一个压缩格式的 ASCII 字符串来表现一系列的点。编码折线还允许您指定线段的可见缩放级别;这样您就可以指定在各种的缩放级别下如何表现折线的细节。虽然这种方法用起来有些复杂,但是它可以让地图的绘制效率更高。

例如,有 3 个点的 GPolyline 对象通常为:

var polyline = new GPolyline([
   
new GLatLng(39.4419, 116.1419),
   
new GLatLng(39.4519, 116.1519),
   
new GLatLng(39.4619, 116.1819)
], "#FF0000", 10);
map
.addOverlay(polyline);

而与之对应的编码 GPolyline 对象则如下:(请暂时不要关心编码算法的细节)

var encodedPolyline = new GPolyline.fromEncoded({
    color
: "#FF0000",
    weight
: 10,
    points
: "ynvoF{}zcUq}@m}@m}@ozD",
    levels
: "BBB",
    zoomFactor
: 32,
    numLevels
: 4
});
map
.addOverlay(encodedPolyline);

需要注意的两点是:

  1. 首先,编码折线是用一系列的 ASCII 字符来表示一系列的点,正如基本的 GPolyline 对象用一系列经纬度来表示那样。为点序列创建对应 ASCII 编码的算法可以在这里找到(英文)。如果您需要动态地在服务器上计算这些编码的话,那么就需要了解这个算法。但是,如果您仅仅需要将现有点的经纬度转换成编码,那么可以直接使用我们提供的交互工具(英文)
  2. 其次,编码折线允许您指定每个线段的最高可见缩放级别。如果一个点在更高的缩放级别中不可见,那么折线会自动地连接上一个可见点和下一个可见点。注意,这个特性是普通折线不支持的,在较宏观的缩放级别上,它对于加快折线绘制速度非常有利,因为折线的一些细节无需表现出来。例如,当地图缩放到省级的时候,一条用于表现从北京市到上海市驾驶路线的编码折线,就不需要表现出北京市内的具体街道了。

查看示例 (polylineencoding.html)

在地图中使用 XML 和异步 HTTP 通信 (AJAX)

在这里例子里,我们用 GDownloadUrl 方法下载一个包含经纬度列表的 XML 文件("data.xml")。当下载完成,我们用 GXml 类来解析,并为 XML 文档中的每一个点建立一个标注。

var map = new GMap2(document.getElementById("map"));
map
.addControl(new GSmallMapControl());
map
.addControl(new GScaleControl());
map
.setCenter(new GLatLng(39.917, 116.397), 14);

// 从 data.xml 下载数据并加载到地图上,我们期望的格式是:
// <markers>
//   <marker lat="39.441" lng="116.141"/>
//   <marker lat="39.322" lng="116.213"/>
// </markers>
GDownloadUrl("data.xml", function(data, responseCode) {
 
var xml = GXml.parse(data);
 
var markers = xml.documentElement.getElementsByTagName("marker");
 
for (var i = 0; i < markers.length; i++) {
   
var point = new GLatLng(parseFloat(markers[i].getAttribute("lat")),
                            parseFloat
(markers[i].getAttribute("lng")));
    map
.addOverlay(new GMarker(point));
 
}
});

查看示例 (async.html). 本示例使用一个外部的 XML 文件 data.xml.

自定义地图控件

第 2 版的 API 加入了自定义地图控件的功能,和内置的“移动/缩放"控件一样,这是通过继承内置的 GControl 类来实现的。在这个例子中,我们创建一个简单的缩放控件:它采用简单的文字链接按钮,而不像标准 Google 地图 缩放控件那样使用图片按钮。

GTextualZoomControl类实现了GControl 接口中的两个必须的方法:initialize(),它用于创建表现我们的控件的 DOM 元素;getDefaultPosition(),它返回一个 GControlPosition 对象,表示了控件在地图上的默认位置。关于创建自定义控件可重载函数的更多信息,请参见 GControl 类参考

所有的地图控件都必须加入到地图的容器中,这个容器可以通过 GMap2 对象的 getContainer() 方法得到。

// 一个 TextualZoomControl 对象是 GControl 接口的一个示例,它以文字的形式显示
// “放大”、“缩小”两个按钮。(这和内置控件中的图片按钮是不同的)
function TextualZoomControl() {
}
TextualZoomControl.prototype = new GControl();

// 给每个按钮分别创建一个 DIV 元素,并将它们加入到另一个作为容器的 DIV 元素中,
// 这个容器 DIV 将被作为我们的控件元素返回。同时还要将它加入到地图的容器中,只有这样
// GMap2 类才能正确地设置该控件的位置
TextualZoomControl.prototype.initialize = function(map) {
 
var container = document.createElement("div");

 
var zoomInDiv = document.createElement("div");
 
this.setButtonStyle_(zoomInDiv);
  container
.appendChild(zoomInDiv);
  zoomInDiv
.appendChild(document.createTextNode("放大"));
 
GEvent.addDomListener(zoomInDiv, "click", function() {
    map
.zoomIn();
 
});

 
var zoomOutDiv = document.createElement("div");
 
this.setButtonStyle_(zoomOutDiv);
  container
.appendChild(zoomOutDiv);
  zoomOutDiv
.appendChild(document.createTextNode("缩小"));
 
GEvent.addDomListener(zoomOutDiv, "click", function() {
    map
.zoomOut();
 
});

  map
.getContainer().appendChild(container);
 
return container;
}

// 下面的语句表明,默认情况下,这个控件会出现在距离地图左上角 7 像素的位置上
TextualZoomControl.prototype.getDefaultPosition = function() {
 
return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(7, 7));
}

// 设置按钮的样式
TextualZoomControl.prototype.setButtonStyle_ = function(button) {
  button
.style.textDecoration = "underline";
  button
.style.color = "#0000cc";
  button
.style.backgroundColor = "white";
  button
.style.font = "small Arial";
  button
.style.border = "1px solid black";
  button
.style.padding = "2px";
  button
.style.marginBottom = "3px";
  button
.style.textAlign = "center";
  button
.style.width = "6em";
  button
.style.cursor = "pointer";
}

var map = new GMap2(document.getElementById("map"));
map
.addControl(new TextualZoomControl());
map
.setCenter(new GLatLng(39.917, 116.397), 14);

查看示例 (customcontrol.html)

自定义地图覆盖物

Google 地图 API 具有创建自定义地图覆盖物的能力,就像内建的 GMarker GPolyline 对象一样,通过继承内置的 GOverlay 接口即可实现。在这个例子中,我们创建一个矩形覆盖物,它可用于标记地图上的一个矩形区域。

Rectangle 类实现了 GOverlay 接口中四个必要方法:initialize(),用于创建表现覆盖物的 DOM 元素;remove(),用于移除覆盖物;copy(),用于复制该覆盖物,以便于在另一个地图对象中使用它;redraw(),用于在可见区域和缩放级别改变时,重新定位并调节覆盖物的大小。关于创建自定义覆盖物可重载函数的更多信息,请参阅 GOverlay 类参考

构成覆盖物的每一个 DOM 元素都应该属于某个“地图层”, “地图层”定义了覆盖物的 Z 顺序。例如,折线浮在地图之上,所以它们应处于 Z 序最小的 G_MAP_MAP_PANE 层。表示标注影子的元素放置在 G_MAP_MARKER_SHADOW_PANE 层,而标注的前景元素则放置在 G_MAP_MARKER_PANE 层。只有将您的覆盖物放置在正确的层上,才能确保直线画在标注阴影的下面,而信息窗口则显示在其他覆盖物之上。在这个例子里,我们希望将覆盖物紧贴于地图之上,所以,我们把它放置在 Z 序最小的 G_MAP_MAP_PANE 层(和 GPolyline 一样)。在类参考中,您可以得到完整的地图层的列表。

// Rectangle 是一个简单的覆盖物,它能够在地图上“框住”一个经纬度的区域,
// 它的边框宽度和颜色都是可定制的
function Rectangle(bounds, opt_weight, opt_color) {
 
this.bounds_ = bounds;
 
this.weight_ = opt_weight || 2;
 
this.color_ = opt_color || "#888888";
}
Rectangle.prototype = new GOverlay();

// 创建用于表示该矩形区域的 DIV 元素
Rectangle.prototype.initialize = function(map) {
 
// 创建用于表示该矩形区域的 DIV 元素
 
var div = document.createElement("div");
  div
.style.border = this.weight_ + "px solid " + this.color_;
  div
.style.position = "absolute";

 
// 我们希望将覆盖物紧贴于地图之上,因此我们把它放置在 Z 序最小的 G_MAP_MAP_PANE 层,
 
// 事实上,这也是地图本身的 Z 顺序,即在标注的影子之下
  map
.getPane(G_MAP_MAP_PANE).appendChild(div);

 
this.map_ = map;
 
this.div_ = div;
}

// 从地图层移除 DIV 元素
Rectangle.prototype.remove = function() {
 
this.div_.parentNode.removeChild(this.div_);
}

// 将此覆盖物的数据复制到另一个 Rectangle 对象
Rectangle.prototype.copy = function() {
 
return new Rectangle(this.bounds_, this.weight_, this.color_,
                       
this.backgroundColor_, this.opacity_);
}

// 根据当前的视角和缩放级别重新绘制矩形对象
Rectangle.prototype.redraw = function(force) {
 
// 只有当坐标系改变时,我们才需要重绘
 
if (!force) return;

 
// 根据当前显示区域的经纬度坐标,计算 DIV 元素的左上角和右下角的像素坐标
 
var c1 = this.map_.fromLatLngToDivPixel(this.bounds_.getSouthWest());
 
var c2 = this.map_.fromLatLngToDivPixel(this.bounds_.getNorthEast());

 
// 根据计算得到的坐标放置我们的 DIV 元素
 
this.div_.style.width = Math.abs(c2.x - c1.x) + "px";
 
this.div_.style.height = Math.abs(c2.y - c1.y) + "px";
 
this.div_.style.left = (Math.min(c2.x, c1.x) - this.weight_) + "px";
 
this.div_.style.top = (Math.min(c2.y, c1.y) - this.weight_) + "px";
}

var map = new GMap2(document.getElementById("map"));
map
.addControl(new GSmallMapControl());
map
.addControl(new GScaleControl());
map
.setCenter(new GLatLng(39.917, 116.397), 14);

// 将矩形覆盖物放置在地图中心,其大小大约为地图大小的四分之一
var bounds = map.getBounds();
var southWest = bounds.getSouthWest();
var northEast = bounds.getNorthEast();
var lngDelta = (northEast.lng() - southWest.lng()) / 4;
var latDelta = (northEast.lat() - southWest.lat()) / 4;
var rectBounds = new GLatLngBounds(
   
new GLatLng(southWest.lat() + latDelta, southWest.lng() + lngDelta),
   
new GLatLng(northEast.lat() - latDelta, northEast.lng() - lngDelta));
map
.addOverlay(new Rectangle(rectBounds));

查看示例 (customoverlay.html)

标注管理器示例

要使用标注管理器,请创建一个 GMarkerManager 对象。在最简单的情形下,将一个地图作为参数传递给它即可。

var map = new GMap2(document.getElementById("map"));
var mgr = new GMarkerManager(map);

同时您也可以指定一些参数,来调整标注管理器的性能。这些参数被包装在对象 GMarkerManagerOptions  中,它包含以下一些属性:

  • maxZoom: 指定受此标注管理器管理的最大缩放级别,默认值为 Google 地图的最大缩放级别
  • borderPadding: 指定标注管理器所管理的额外区域,以像素为单位。为了实现平滑的拖动效果,处于当前地图可见区域以外的部分标注也应该显示在地图上,这个额外的区域就是 borderPadding,其默认值为 100 像素
  • trackMarkers: 指定标注管理器是否要监控标注的移动。如果您希望能够通过 setPoint() 方法来改变受标注管理器管理的标注位置,那么就将它设置为 true.。此属性的默认值为 false.。需要注意的是,如果这个属性的值为 false.,那么当标注移动时,它们将在原来的位置和新的位置同时出现。

GMarkerManagerOptions 对象是一个简单对象,不需要用构造函数的方式来声明它。

var map = new GMap2(document.getElementById("map"));
var mgrOptions = { borderPadding: 50, maxZoom: 15, trackMarkers: true };
var mgr = new GMarkerManager(map, mgrOptions);

创建了标注管理器之后,您就可以向它添加标注了。 GMarkerManager 提供了两个方法 addMarker() 和  addMarkers(),分别用于一次添加单个标注以及批量地添加。只要在当前地图的显示区域和缩放级别是可见的,采用 addMarker() 方法添加的单个标注会立即出现在地图中。

我们推荐用更高效的 addMarkers() 方法批量地添加标注。采用 addMarkers() 方法添加的标注并不会立即出现在地图中,您需要调用 GMarkerManager 对象的 refresh() 方法来显示它们,该方法会把当前可见的以及处于额外区域之内的标注添加到地图上。在此之后,标注管理器就会在地图的 “moveend” 事件中,自动更新应该显示的标注。

标注管理器例子:天气预报图

下面的例子创建了一个假想的天气预报图。在缩放级别 4 上,会显示 20 个随机分布的气象图标;在缩放级别 6 上,很多地、市级行政单位已经能从地图上看到了,因此我们将显示额外的 200 个标注;最后,在缩放级别 8 上,很多县级行政单位已经能从地图上看到了,此时将有 1000 余个气象标注被显示。

function setupMap() {
 
if (GBrowserIsCompatible()) {
    map
= new GMap2(document.getElementById("map"));
    map
.addControl(new GLargeMapControl());
    map
.setCenter(new GLatLng(37, 107), 4);
    window
.setTimeout(setupWeatherMarkers, 0);
 
}
}

function getWeatherMarkers(n) {
 
var batch = [];
 
for (var i = 0; i < n; ++i) {
    batch
.push(new GMarker(getRandomPoint(), { icon: getWeatherIcon() }));
 
}
 
return batch;
}

function setupWeatherMarkers() {
  mgr
= new GMarkerManager(map);
  mgr
.addMarkers(getWeatherMarkers(20), 3);
  mgr
.addMarkers(getWeatherMarkers(200), 6);
  mgr
.addMarkers(getWeatherMarkers(1000), 8);
  mgr
.refresh();
}

查看示例 (weather_map.html)

疑难解答

如果您的代码无法正常运行,以下给出了一些可尝试的解决方法

  • 请确保您的 API Key 是有效的
  • 请检查您是从 ditu.google.com 而不是 maps.google.com 下载包含 API 的脚本文件,即您的 <script> 标签应该类似这样:
    <script src="http://ditu.google.com/maps?file=api&v=2&key=abcdefg"        type="text/javascript"></script>
  • 检查是否有输入错误,尤其要注意的是,JavaScript 是大小写敏感的
  • 使用 JavaScript 调试器调试。在 Firefox 中,您可以用内置的 JavaScript 控制台,或者 Venkman 调试器;在 IE 中,您可以使用 Microsoft 脚本调试器
  • 地图 API 讨论组上搜索您的问题。如果没有找到您想要的解答,请发布您的问题,并提供一个链接指向能说明您的问题的网页。
  • 从第三方获得其他开发资料

其它资料

这里给出一些额外资料,请注意这些站点不受 Google 的管理,Google 也不为其提供技术支持

  • Mapki 是一个流行的 Google Maps API 论坛,包括它的 FAQ 页. (英文)
  • Zmap 是一个流行的中文地图 API 网站

API 概览

API 概览介绍了 地图 API 的一些核心概念。关于本 API 的全部类及方法的参考,请参见 地图 API 类参考

GMap2 类

GMap2 类的实例表示网页中的一个地图。您可以创建任意多个该类的实例(一个实例就对应页面上的一个地图)。在创建地图实例时,您需要指定一个包含该地图的页面元素(通常是 div 元素),这个元素称为地图控件的容器。除非您明确地指定了地图的大小,默认情况下地图大小会取决于容器的尺寸。

GMap2 类提供了控制地图中心和缩放级别的方法、添加删除覆盖物(例如 GMarker GPolyline)的方法,以及用于打开气泡提示窗口的方法(正如您在 Google 地图 中看到的)。更多信息参见气泡提示窗口

关于 GMap2 类的更多信息,请参见 GMap2 类参考

事件

利用事件处理函数,您可以给您的程序加入动态效果。每个对象都关联着一些事件,您的程序可以用静态方法 GEvent.addListener GEvent.bind 来"监听"这些事件。例如,下面的代码片断在每次用户点击地图时显示一个对话框:

var map = new GMap2(document.getElementById("map"));
map
.setCenter(new GLatLng(39.917, 116.397), 14);
GEvent.addListener(map, "click", function() {
  alert
("您点击了地图。");
});

GEvent.addListener 的第三个参数是一个函数,这个函数将用于处理该事件。如果要用类实例的方法来处理事件,可以用 GEvent.bind 方法。在下面的例子中,MyApplication 类实例把地图事件关联到它的方法上,在触发时修改对象的状态:

function MyApplication() {
 
this.counter = 0;
 
this.map = new GMap2(document.getElementById("map"));
 
this.map.setCenter(new GLatLng(39.917, 116.397), 14);
 
GEvent.bind(this.map, "click", this, this.onMapClick);
}

MyApplication.prototype.onMapClick = function() {
 
this.counter++;
  alert
("这是您第 " + this.counter + " 次点击地图");
}

var application = new MyApplication();

查看示例 (bind.html)

气泡提示窗口

气泡提示窗口可以浮动在地图之上并显示 HTML 内容。每个地图都有一个气泡窗口,它包含一个内容区域和一个锥形箭头,锥形的箭头指向地图上的指定点。例如,当您在 Google 地图上点击一个标记,就可以看到气泡提示窗口。

一个地图不能同时显示多个气泡提示窗口,但是您可以根据需要移动该窗口或者修改它的内容。

气泡提示窗口的基本方法是 openInfoWindow,它的参数包括一个点和一个 HTML DOM 元素。HTML DOM 元素会被添加到气泡提示窗口的容器内,而气泡提示窗口的锥形箭头会指向给定的点。

openInfoWindowHtml 方法很类似,但是它接受 HTML 字符串作为参数,而不是 HTML DOM 元素。

如果要在标记等覆盖对象之上显示气泡提示窗口,您可以设置第三个可选参数:气泡提示窗口尖端和给定点之间的偏移量。例如,如果您的标记高为10个像素,那么您可以把像素偏移量 GSize(0, -10) 传给方法。

GMarker类提供了openInfoWindow 方法,它会自动计算与您的图标形状及尺寸相应的偏移量。

更多信息请参见 GMap2GMarker 的类参考。

地图覆盖物

覆盖物是覆盖在地图的某个固定经纬度坐标上的对象,当您拖动地图或者改变地图类型的时候,他们也会跟着移动。

地图 API 支持两种类型的覆盖对象:标注:地图上的图标;折线:用一系列点连成的线。

标注和图标


GMarker
类的构造函数有两个参数,一个是图标,一个是点。此外,它还支持一些事件,如"点击"事件。在地图上创建标注的简单例子,请参见上面的 overlay.html

创建标注最麻烦的操作是指定一个图标,其原因是地图 API 中的一个图标需要涉及多个图片。

每个图标包含一个前景图片和一个影子图片。影子是由前景图片向右上方倾斜 45 度构成的,而影子图片的左下角应该和前景图片的左下角对齐。影子图片应该是 24 位的 PNG 格式,它的背景应该是半透明的,这样影子的边缘才能在地图上正确显示。

GIcon 类需要您在初始化图标时指定这些图片的尺寸,这样 地图 API 就能用恰当的尺寸来创建这些图片。以下是创建一个图标所需的最少代码(图标来自 Google 地图):


 

var icon = new GIcon();
icon
.image = "http://ditu.google.com/mapfiles/marker.png";
icon
.shadow = "http://ditu.google.com/mapfiles/shadow50.png";
icon
.iconSize = new GSize(20, 34);
icon
.shadowSize = new GSize(37, 34);

GIcon 类还有几个属性,当您的图标想得到最好的浏览器兼容性和功能特性时需要设置它们。例如,imageMap 属性可以用来设定图标的不透明区域的形状。如果该属性没有设置,则在 Firefox / Mozilla下,整个图片范围(包括透明区域)都可以点击。更多的信息参见 GIcon 类参考

折线

GPolyline 类的构造函数以一个点的数组为参数,并按照给定点的顺序创建连接这些点的一系列线段。您还可以指定这些线段的颜色、宽度和透明度。颜色应该使用 16 进制的数字表示,如 #ff0000。而不要用redGPolyline 类不能解析颜色名。

下面的代码片断创建两点之间 10 个像素宽的红色折线:

var polyline = new GPolyline([
 
new GLatLng(39.917, 116.397),
 
new GLatLng(39.927, 116.387)
], "#ff0000", 10);
map
.addOverlay(polyline);

在 Internet Explorer 下,Google 地图使用 VML 来绘制折线(更多信息请参见 XHTML 和 VML)。在其它浏览器中,我们会从 Google 服务器请求线的图片并覆盖在地图上,当地图缩放或拖动的时候会刷新图片。

控件

想为您的地图加入缩放按钮之类的控件,请使用 addControl 方法。地图 API 内置了很多可以用在您地图上的控件:

  • GLargeMapControl - 大号平移和缩放控件,位置是左上角。
  • GSmallMapControl - 小号平移和缩放控件,位置是左上角。
  • GSmallZoomControl - 小号缩放控件,位置是左上角。
  • GScaleControl - 地图比例尺。
  • GOverviewMapControl - 位于屏幕右下角、可以收起来的缩略图。

例如,如果想在您的地图上添加一个平移和缩放控件,您可以使用下面的这行代码:

map.addControl(new GLargeMapControl());

addControl 方法有一个可选参数 GControlPosition,通过它您自己可以指定控件的位置。如果省略了这个参数,地图 API 将采用控件的默认位置。这个例子加入一个比例尺控件到距离地图右上角 10 个像素的位置:

map.addControl(new GScaleControl(),
               
new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(10, 10)));

更多信息请查看 GControlPosition 类参考.

XML 和 RPC

Google 地图 API 采用工厂方法来创建 XmlHttpRequest 对象,它支持新版本 IE,Firefox 和 Safari。下面的例子下载一个叫做 myfile.txt 的文件,然后用 JavaScript 的 alert 函数显示其内容:

var request = GXmlHttp.create();
request
.open("GET", "myfile.txt", true);
request
.onreadystatechange = function() {
 
if (request.readyState == 4) {
    alert
(request.responseText);
 
}
}
request
.send(null);

这个 API 还引入了类似典型的 HTTP GET 请求的方法:GDownloadUrl,它不需要像 XmlHttpRequest 那样检查 readyState。上面的例子可用 GDownloadUrl 函数改写如下:

GDownloadUrl("myfile.txt", function(data, responseCode) {
  alert
(data);
});

您可以用静态方法 GXml.parse 来解析 XML 文档,它的参数是一个 XML 字符串。这个方法兼容大多数现代浏览器,如果遇到不支持本地 XML 解析的浏览器,它会抛出一个异常。

更多信息请参见 GXmlHttpGXml 的类参考。

减少浏览器内存泄露

Google 地图 API 鼓励使用函数闭包(匿名函数)。由于 API 的事件处理机制会把事件关联到 DOM 结点上,这不可避免地会导致一些浏览器内存泄露,尤其是在 Internet Explorer 中。第 2 版的 API 引入了一个新的方法:GUnload(),它会消除大多数导致内存泄露的循环引用。 因此,您应该在您的网页的 unload 事件中调用 GUnload() 方法,以避免您应用程序可能带来的内存泄露问题。

<body onunload="GUnload()">

这个函数可以消除 Google 地图在 Internet Explorer 下的内存泄露,但是如果您特别关心内存消耗问题,您仍旧应该用 Drip 等工具测试您自己网站的内存泄露情况。

 

 

posted on 2010-07-26 11:29  GIS的学习  阅读(2892)  评论(0编辑  收藏  举报