轻松实现 HTML、ASP.NET、PHP、JSP 等的 Google 地图






4.84/5 (115投票s)
本文将为您提供关于如何在网页中添加 Google 地图的完整知识,包括 JavaScript 的使用、Geocoder 的使用、InfoWindow 的使用、Marker 的使用、Tabbed Markers、Maximising marker、创建上下文菜单以及地图中的街景。
目录
引言
本文将指导您了解 JavaScript 的一些用法,更准确地说,将使您能够轻松地在网页中使用 Google 地图。Google 提供了网络服务,任何人都可以免费连接和使用其服务。当然,使用 Gmap 存在一些限制。它们有两种地图版本,一种是标准用途,免费提供;另一种是 Google 地图企业解决方案。
如果您想在网站上添加一个可以从任何地方访问的 Google 地图,即只需使用链接即可访问,则无需为使用其 API 向 Google 付费。但是,如果您希望限制地图访问仅限于通过有效登录,则需要向 Google 付费。我使用一个简单的 HTML 页面来添加 Gmap。稍后,我也会使用其他方法使 Gmap 看起来更生动。
使用 Gmap 到您的应用程序所需的就是一个 Google 帐户。您可以免费注册一个帐户。只需在此处注册。
您可以免费注册一个帐户,然后通过点击“立即创建帐户”来在您的网站上使用 Google 地图。创建帐户后,只需在需要时使用您的 `userid` 和 `password` 登录即可。
背景
要在您的网站上使用 Google 地图,您需要了解一些 JavaScript 知识,即如何从 Web 控件调用函数。我将详细介绍所有内容,但您需要掌握所有这些。
示例
我正在创建一个 HTML 页面来实现这个项目。您可以使用任何项目,并使用任何服务器端语言动态实现地图。
示例 1:入门
//Use of Gmap in your web page
//
<!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>My Locations</title>
<script src="http://maps.google.com/maps?file=api&v=2&
key=ABQIAAAAcl" type="text/javascript"></script>
<script type="text/javascript">
function load()
{
if (GBrowserIsCompatible()) {
var point;
var map=new GMap2(document.getElementById("map"));
map.addControl(new GOverviewMapControl());
map.enableDoubleClickZoom();
map.enableScrollWheelZoom();
map.addControl(new GMapTypeControl());
map.addControl(new GSmallMapControl());
var address='<img src="myimage.gif" width=150 height=40/><br/>' +
<font size="2" face="Arial"><b>INDIA</b><br/><br/>Home.<br/>' +
New York City<br/><br/>America<br/>Ph.: 23743823</font>';
var marker = new GMarker(point);
map.setCenter(point,17);
map.addOverlay(marker);
map.setMapType(G_HYBRID_MAP);
GEvent.addListener(marker, "click", function() {
marker.openInfoWindowHtml(address);});
marker.openInfoWindowHtml(address);
}
}
</script>
<body onload="load();" onunload="GUnload()" style="
background-color:Transparent">
<div id="map" style="width: 900px; height: 500px"></div>
</body>
</html>
说到代码,首先在您的网页中,您需要添加一个 `
<div id="map" style="width: 900px; height: 500px"></div>
现在,我在 `body` 加载时调用了一个 JavaScript 函数,因此,在我的示例应用程序中,一旦页面加载到您的浏览器中,您将看到一个加载的 Gmap。因此,我创建了一个 `load` JavaScript 函数,将在打开网页时立即调用。然后在页面加载期间,我们添加了一个动态 JavaScript 文件,该文件将依赖于 Web 主机。这一行...
<script src="http://maps.google.com/maps?file=api&v=2&
key=ABQIAAAAcl" type="text/javascript"></script>
...从 Google 添加了一个文件。这很重要,因为该文件将为您创建整个地图。您唯一需要的是为您的 Web 主机生成一个 API 密钥。无论是本地主机,都可以使用 `https://`。只需点击下方即可获取密钥。
您将在此处获取密钥,只需将密钥替换为 JavaScript 行的 `key` 属性即可。
完成此操作后,我使用了 `GBrowserIsCompatible()`,这是一个仅当您的浏览器与 Gmap 兼容时才返回 `true` 的函数。下一行会将 Gmap 控件加载到 `div` 控件中。`GMap2` 函数接收要加载的控件,并返回一个以后可以引用的 `map` 对象。然后,`map.addControl(new GOverviewMapControl());` 将向地图添加一个名为 `GOverviewMapControl` 的新控件。
它将是地图右下角的一个地图概览。
我可以通过 `addControl` 函数添加更多控件。我使用了 `GSmallMapControl()`。
来为地图添加缩放控件,以及新的 `GMapTypeControl`()
作为新的地图类型控件,方式类似。地图主要有 3 种类型:普通、卫星和混合。您将在地图上找到这些选项。
`enableDoubleClickZoom` 和 `enableScrollWheelZoom` 将简单地为您启用地图的这些功能。
之后,我在我的应用程序中放置了一个标记。标记是可以在地图上指向某个位置的图像。要放置标记,您需要一个纬度和经度,应通过 `GLatLng()` 函数传递以获取有效点。我还制作了一个 HTML,可以在地图上显示。我让一个 `var` address 来存储 HTML。稍后,我使用这些纬度和经度在地图上创建了一个标记。`GMarker` 将创建一个标记,`addOverlay()` 将标记添加到表单中。
`GEvent.addListener` 将向地图添加一个监听器,通过该监听器地图将作出响应。我向地图添加了一个单击事件监听器,因此当单击地图时,它将显示标记的 `InfoWindow`。`openInfoWindowHtml()` 将为我打开信息窗口 HTML。就是这样。您已经创建了一个简单的地图并将其添加到了您的 HTML 页面中。
看看截图
示例 2:在自定义地图上创建折线
现在,让我们通过添加折线使其更高级。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//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>
<title>Untitled Page</title>
<script src="http://maps.google.com/maps?file=api&v=2&
key=ABQIA" type="text/javascript"></script>
<script type="text/javascript">
function loadEarth(mapdiv) {
if (GBrowserIsCompatible()) {
var point;
if(!mapdiv)return true;
var map=new GMap2(document.getElementById("map"));
map.addControl(new GOverviewMapControl());
map.enableDoubleClickZoom();
map.enableScrollWheelZoom();
map.addControl(new GMapTypeControl());
map.addControl(new GSmallMapControl());
var marker = new GMarker(new GLatLng(37.4419,-122.1419));
map.setCenter(new GLatLng(37.4419,-122.1419),17);
GEvent.addListener(marker, "click", function() {
marker.openInfoWindowHtml("hii");});
map.addOverlay(marker);
map.setCenter(new GLatLng(37.4419, -122.1419), 16);
map.setMapType(G_SATELLITE_MAP);
var polyline = new GPolyline([new GLatLng(37.4419, -122.1419),
new GLatLng(37.4519, -122.1519),
new GLatLng( 37.4619, -122.1819)], "#3333cc", 10);
}
map.addOverlay(polyline);
}
</script>
</head>
<body onload="loadEarth('map')" onunload="GUnload()" style="
background-color:Transparent">
<div id="map" style="width: 500px; height: 300px"></div>
</body>
</html>
在上面的示例中,我在创建标记后立即取了 3 个点,并在这些点上绘制了折线。
`GPolyline()` 将使用点的数组创建一个 `polyline` 对象,具有特定的颜色,此处我使用了十六进制代码,以及宽度,此处为 10。之后,我使用 `addOverlay` 函数将折线添加到我们的实际地图中。
请记住,在使用折线时,需要添加 `vml` 命名空间。我们还需要使用严格的 DTD 标准才能在地图上显示折线。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//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">
否则,折线将不会显示在您的地图上。看看截图
示例 3:为经纬度进行地址编码
在我的下一个示例中,我将使用 `Geocoder` 功能到我的地图,这样您就可以从搜索文本框中搜索任何地址,并且 geocoder 将为您搜索这些地址。
<!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>Coder Page</title>
<script src="http://maps.google.com/maps?file=api&v=2&key=ABQIAA"
type="text/javascript"></script>
<script language="'Javascript'" type='text/javascript'>
var map = null;
var geocoder = null;
function load() {
if (GBrowserIsCompatible()) {
map = new GMap2(document.getElementById("map"));
map.setCenter(new GLatLng(37.4419, -122.1419), 13);
geocoder = new GClientGeocoder();
}
}
function showAddress(address) {
if (geocoder) {
geocoder.getLatLng(
address,
function(point) {
if (!point) {
alert(address + " not found");
} else {
map.setCenter(point, 17);
var marker = new GMarker(point);
map.addOverlay(marker);
marker.openInfoWindowHtml(address);
}
}
);
}
}
</script>
</head>
<body onload="load()" onunload="GUnload()">
<input type="text" size="60" name="address" id="addr"
value="India" />
<input type="button" value="Go!"
onclick="showAddress(document.getElementById("addr").value);
return false"/>
</p>
<div id="map" style="width: 500px; height: 300px"></div>
</body>
</html>
在上面的示例中,我添加了另一个函数,该函数使我们能够调用任何地址,并将地址替换为以纬度和经度为单位的点。`GClientGeocoder()` 将一个 geocode 对象返回给客户端浏览器,该对象稍后可用于从任何文本地址获取点。Google 估算每次 geocode 调用大约需要 1.73 秒。所以它并没有那么慢。现在,为了搜索地址,我创建了一个 `button` 和一个 `textbox`,用于从用户那里获取地址。`showaddress` 函数将从用户那里获取一个地址,并在该位置创建一个标记,并打开该标记的 `infowindow`。如果找不到点,它会返回一个警报。因此,点击按钮时,它将调用 `showaddress` 函数,它将显示位置。
看看我们迄今为止所构建内容的快照
示例 4:创建上下文菜单
嗯,在我的下一个示例中,我将添加一个示例,该示例可以更好地演示 Gmap 的使用。我将添加上下文菜单。先看看代码
var map = null;
var geocoder = null;
var contextmenu;
function load(loc) {
if (GBrowserIsCompatible()) {
var point;
map=new GMap2(document.getElementById("map"));
map.addControl(new GOverviewMapControl());
map.enableDoubleClickZoom();
map.enableScrollWheelZoom();
map.addControl(new GMapTypeControl());
map.addControl(new GLargeMapControl());
createContextMenu(map);
var address='<font size="2" face="Arial"><b>INDIA</b><br/>
<br/>XYZ Inc.<br/>New York City <br/>
America<br/>Ph.: 343254543</font>';
point = new GLatLng(22.592057,88.421815);
var marker = new GMarker(point);
map.setCenter(point,17);
map.addOverlay(marker);
map.setMapType(G_HYBRID_MAP);
GEvent.addListener(marker,
"click", function() {marker.openInfoWindowHtml(address);});
marker.openInfoWindowHtml(address);
}
}
function createContextMenu(map)
{
contextmenu = document.createElement("div");
contextmenu.style.visibility="hidden";
contextmenu.style.background="#ffffff";
contextmenu.style.border="1px solid #8888FF";
contextmenu.innerHTML = '<a href="javascript:zoomIn()">
<div class="context"> Zoom in </div></a>'
+ '<a href="javascript:zoomOut()">
<div class="context"> Zoom out </div></a>'
+ '<a href="javascript:zoomInHere()">
<div class="context"> Zoom in here </div></a>'
+ '<a href="javascript:zoomOutHere()">
<div class="context"> Zoom out here </div></a>'
+ '<a href="javascript:centreMapHere()">
<div class="context"> Centre map here </div></a>';
map.getContainer().appendChild(contextmenu);
GEvent.addListener(map,"singlerightclick",function(pixel,tile)
{
clickedPixel = pixel;
var x=pixel.x;
var y=pixel.y;
if (x > map.getSize().width - 120)
{
x = map.getSize().width - 120
}
if (y > map.getSize().height - 100)
{
y = map.getSize().height - 100
}
var pos = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(x,y));
pos.apply(contextmenu);
contextmenu.style.visibility = "visible";
});
GEvent.addListener(map, "click", function()
{
contextmenu.style.visibility="hidden";
});
}
function zoomIn()
{
map.zoomIn();
contextmenu.style.visibility="hidden";
}
function zoomOut()
{
map.zoomOut();
contextmenu.style.visibility="hidden";
}
function zoomInHere()
{
var point = map.fromContainerPixelToLatLng(clickedPixel)
map.zoomIn(point,true);
contextmenu.style.visibility="hidden";
}
function zoomOutHere()
{
var point = map.fromContainerPixelToLatLng(clickedPixel)
map.setCenter(point,map.getZoom()-1);
contextmenu.style.visibility="hidden";
}
function centreMapHere()
{
var point = map.fromContainerPixelToLatLng(clickedPixel)
map.setCenter(point);
contextmenu.style.visibility="hidden";
}
在此示例中,当用户在地图上的任何位置右键单击时,我添加了一个自定义 `div` 控件。当用户右键单击地图时应注册的事件是 `GEvent.addListener(map,"singlerightclick",function(pixel,tile)`。我通过从像素获取点,在右键单击发生的位置创建了该 `div`。当选项被点击时,`div` 会执行一些函数调用。这些调用 `map.zoomIn`、`ZoomOut` 函数。当选项起作用时,容器被设置为隐藏,以消除地图上的自定义 `div` 控件。
查看截图
示例 5:带最大化功能的选项卡式信息窗口
嗯,在这个例子中,我将为您介绍如何创建选项卡式信息窗口以及一个最大化 `infowindow` 的选项,以便您可以显示其中的网页。请看下面的代码
var map = null;
var geocoder = null;
function load(loc) {
if (GBrowserIsCompatible()) {
var point;
var map=new GMap2(document.getElementById("map"));
map.addControl(new GOverviewMapControl());
map.enableDoubleClickZoom();
map.enableScrollWheelZoom();
map.addControl(new GMapTypeControl());
map.addControl(new GSmallMapControl());
var address='<font size="2" face="Arial"><b>INDIA</b><br/><br/>
XYZ Inc.<br/>New York City <br/>America<br/>Ph.: 343254543</font>';
point = new GLatLng(22.592057,88.421815);
var marker = new GMarker(point);
map.setCenter(point,17);
map.addOverlay(marker);
map.setMapType(G_HYBRID_MAP);
GEvent.addListener(marker, "click", function() {
marker.openInfoWindowTabsHtml(
[new GInfoWindowTab("BASIC",address),
new GInfoWindowTab("Advanced","<b>Dont forget to click on
<br/>Maximize button on this window with + sign</b>")],
{maxUrl:"http://dotnetricks.blogspot.com"});
});
}
}
嗯,您可以看到 `GEvent.addListener` 这行代码,其中我们调用 `openInfoWindowTabsHtml` 而不是 `openInfoWindow`。此函数使我们能够创建选项卡式窗口。参数是 `GInfoWindowTab` 的选项卡数组,它接受两个参数,第一个是标题,第二个是 HTML 中的内容。`openInfoWindowTabsHtml` 的第二个参数是选项,我使用了 `maxUrl` 选项,该选项将在窗口上创建一个最大化按钮。我也可以在普通标记中使用此选项。现在让我们看看快照
此窗口显示带有两个选项卡的选项卡式窗口
- 基本选项卡
- 高级
当您点击 **关闭** 按钮旁边的 + 按钮时,它将在 Gmap 中打开一个 HTML 窗口。查看快照
示例 6:捕获数据客户端事件
在这个演示中,我将使用一个新的事件处理程序 `Dragend` 和 `moveend` 处理程序。看看简单的代码
<script type="text/javascript">
function load() {
if (GBrowserIsCompatible()) {
var map = new GMap2(document.getElementById("map"));
map.addControl (new GSmallMapControl());
map.addControl(new GMapTypeControl());
var center = new GLatLng(-22.98699983834975, -43.210344314575195);
map.setCenter(center, 11);
map.setMapType(G_SATELLITE_MAP);
geocoder = new GClientGeocoder();
var marker = new GMarker(center, {draggable: true});
map.addOverlay(marker);
document.getElementById("lat").value = center.lat();
document.getElementById("lng").value = center.lng ();
geocoder = new GClientGeocoder();
GEvent.addListener(marker, "dragend", function() {
var point =marker.getPoint();
map.panTo(point);
document.getElementById("lat").value = point.lat();
document.getElementById("lng").value = point.lng();
});
GEvent.addListener(map, "moveend", function() {
map.clearOverlays();
var center = map.getCenter();
var marker = new GMarker(center, {draggable: true});
map.addOverlay(marker);
document.getElementById ("lat").value = center.lat();
document.getElementById("lng").value = center.lng();
GEvent.addListener(marker, "dragend", function() {
var point =marker.getPoint();
map.panTo(point);
document.getElementById("lat").value = point.lat();
document.getElementById("lng").value = point.lng();
});
});
}
}
function showAddress(address) {
var map = new GMap2(document.getElementById("map"));
map.addControl(new GSmallMapControl());
map.addControl(new GMapTypeControl());
if (geocoder) {
geocoder.getLatLng (
address,
function(point) {
if (!point) {
alert(address + " city not found !");
}
else {
document.getElementById("lat").value = point.lat();
document.getElementById("lng").value = point.lng();
map.clearOverlays()
map.setCenter(point, 14);
var marker = new GMarker(point, {draggable: true});
map.addOverlay(marker);
GEvent.addListener(marker, "dragend", function() {
var pt =marker.getPoint();
map.panTo(pt);
document.getElementById("lat").value = pt.lat();
document.getElementById("lng").value = pt.lng();
});
GEvent.addListener(map, "moveend", function() {
map.clearOverlays();
var center = map.getCenter();
var marker = new GMarker(center, {draggable: true});
map.addOverlay(marker);
document.getElementById ("lat").value = center.lat();
document.getElementById("lng").value = center.lng();
GEvent.addListener(marker, "dragend", function() {
var pt =marker.getPoint();
map.panTo(pt);
document.getElementById("lat").value = pt.lat();
document.getElementById("lng").value = pt.lng();
});
});
}}
);
}}
</script>
在这个例子中,当用户拖动地图时,它会自动将坐标放入名为 `lat` 和 `lng` 的表单文本框中。为此,我创建了一个叠加标记,然后使用 `getPoint()` 函数检索该点。
这是一个简单的例子...只是一个演示。我还包括了 geocoder,因此用户也可以搜索位置。
示例 7:MarkerManager 和侧边栏
在这个示例中,您将使用 `MarkerManager` 和 `Sidebar` 来显示标记链接。
Google 的 Marker Manager 用于管理大量标记。请看下面的示例
<!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>
<title>Google Maps</title>
<script src="http://maps.google.com/maps?file=api&v=2&
key=ABQIAAAAclK0B2lXQwV5lPy1rLiTFBSN1aiKepvDswXjKa4j2DDWdYvOjh
QMO1tywqS8ObgP5dtO70AyyArhzA" type="text/javascript"></script>
</head>
<body onunload="GUnload()">
<!-- you can use tables or divs for the overall layout -->
<table border=1>
<tr>
<td>
<div id="map" style="width: 550px; height: 450px"></div>
</td>
<td width = 150 valign="top" style="text-decoration: underline; color: #4444ff;">
<div id="side_bar"></div>
</td>
</tr>
</table>
<script type="text/javascript">
//<![CDATA[
if (GBrowserIsCompatible()) {
// this variable will collect the html which will eventually be placed
// in the side_bar
var side_bar_html = "";
// arrays to hold copies of the markers and html used by the side_bar
// because the function closure trick doesnt work there
var gmarkers = [];
var i = 0;
var lastlinkid;
// A function to create the marker and set up the event window
function createMarker(point,name,html) {
var marker = new GMarker(point);
var linkid = "link"+i;
GEvent.addListener(marker, "click", function() {
marker.openInfoWindowHtml(html);
document.getElementById(linkid).style.background="#ffff00";
lastlinkid=linkid;
});
// save the info we need to use later for the side_bar
gmarkers[i] = marker;
// add a line to the side_bar html
side_bar_html += '<div id="'+linkid+'">
<a href="javascript:Linkclicked(' + i + ')">'
+ name + '</a><br></div>';
i++;
return marker;
}
// This function picks up the click and opens the corresponding info window
function Linkclicked(i) {
GEvent.trigger(gmarkers[i], "click");
}
// create the map
var map = new GMap2(document.getElementById("map"));
map.addControl(new GLargeMapControl());
map.addControl(new GMapTypeControl());
map.setCenter(new GLatLng( 43.907787,-79.359741), 8);
var mm = new GMarkerManager(map);
// add the points
var point = new GLatLng(43.65654,-79.90138);
var marker = createMarker(point,"This place","This is The First Info")
var point = new GLatLng(43.91892,-78.89231);
var marker = createMarker(point,"That place","This is The Second Info")
var point = new GLatLng(43.82589,-78.89231);
var marker = createMarker(point,"The other place","This is The Third Info")
GEvent.addListener(map,"infowindowclose", function() {
document.getElementById(lastlinkid).style.background="#ffffff";
});
mm.addMarkers(gmarkers,0,17);
mm.refresh();
// put the assembled side_bar_html contents into the side_bar div
document.getElementById("side_bar").innerHTML = side_bar_html;
}
else {
alert("Sorry, the Google Maps API is not compatible with this browser");
}
//]]>
</script>
</body>
</html>
在这里,我放置了一个 markermanager 和一个数组。我将所有标记放入 markermanager 中,以便以后可以刷新、删除或添加它们。链接是使用数组创建的,并且与正确的标记正确映射。查看链接
示例 8:绘制自定义标记
将信息窗口的背景颜色更改为自定义颜色是一个常见问题。一般而言,您可以将 `div` 的背景设置为一种颜色,但这不会更改信息窗口的外部边界。因此,我扩展了 `Tom Morgans Marker` 来创建一个与普通标记完全不同的标记。看看示例
要使用 Tom Morgans Marker,只需在此处下载此 JavaScript:点击此处。
代码如下
<!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 Maps</title>
<script src="http://maps.google.com/maps?file=api&v=2&
key=ABQIAAAAclK0B2lXQwV5lPy1rLiTFBSN1aiKepvDswXjKa4j2DDWdYvOjhQMO1tywqS
8ObgP5dtO70AyyArhzA" type="text/javascript"></script>
<script src="tlabel.2.05.js" type="text/javascript"></script>
</head>
<body onunload="GUnload()">
<div id="map" style="width: 550px; height: 450px"></div>
<script type="text/javascript">
//<![CDATA[
if (GBrowserIsCompatible()) {
var openbubble=true;
var agent = navigator.userAgent.toLowerCase();
// For IE We need to Do this
if ((agent.indexOf("msie") > -1) && (agent.indexOf("opera") < 1)){
var loader = "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(
src='gmarker.png', sizingMethod='crop');";
icon = '<div style="height:34px; width:20px; ' +loader+ '" ></div>'
}
var n=0;
function createTLabel(point,html) {
var label = new TLabel();
label.id = 'Label '+n;
label.anchorLatLng = point;
label.anchorPoint = 'bottomCenter';
label.content = html;
label.markerOffset = new GSize(-1,-5);
map.addTLabel(label);
var obj=document.getElementById(label.id);
GEvent.addDomListener(obj, "click", function() {
//map.openInfoWindowHtml(point, html, {pixelOffset: new GSize(0,-34)} );
});
n++;
}
var map = new GMap2(document.getElementById("map"));
map.addControl(new GLargeMapControl());
map.addControl(new GMapTypeControl());
map.setCenter(new GLatLng(43.907787,-79.359741),8);
// Creating the HTML to show markers
var hContent = '<div style="padding: 0px 0px 13px 0px; background: url(
images/pt_bot_ctr_ora.png) no-repeat bottom center;">
<div style="text-align: center; background-color: #f2c30c; padding: 2px;
font-size: 0.75em; font-weight: bold;" onclick="openInfo(\'hInfo\')">MyInfo
</div>';
hContent+='<div id="hInfo" style="position: absolute; display: none;">';
hContent+='<div style="width: 81px; background-color: #000; padding: 3px;
font-size: 0.75em; color: #fff; text-align: left; border: 1px solid #f2c30c;">
This is my content</div>';
hContent+='</div></div>';
createTLabel(new GLatLng(43.65654,-79.90138),hContent);
}
else {
alert("Sorry, the Google Maps API is not compatible with this browser");
}
function openInfo(d)
{
var obj = document.getElementById(d);
if(openbubble==true)
{
obj.style.display="block";
openbubble=false;
}
else
{
obj.style.display="none";
openbubble=true;
}
}
//]]>
</script>
</body>
</html>
您可以使用 `Gmarker` 数组来存储标签以供将来参考,您也可以向地图添加一个事件,以便通过循环隐藏每个打开的标记。
示例 9:从 GMAP & GPolygon 调用 AJAX
在这个示例中,我将为您提供 `XMLhttpRequest` 和绘制 `GPolygons` 的简要介绍。
首先,请看下面的示例和代码。之后我将进行解释。
<!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>Polygon Demo</title>
<script src="http://maps.google.com/maps?file=api&v=2&
key=ABQIAAAAclK0B2lXQwV5lPy1rL"
type="text/javascript"></script>
<script type="text/javascript">
var map = null;
var polys = [];
var labels = [];
var xmlDoc=null;
function load()
{
if (GBrowserIsCompatible())
{
var point;
map = new GMap2(document.getElementById("map"));
map.addControl(new GLargeMapControl());
map.addControl(new GMapTypeControl());
map.setCenter(new GLatLng(42.16,-100.72),4);
// Read the data from states.xml
var request = GXmlHttp.create();
request.open("GET", "states.xml", true);
request.onreadystatechange = function()
{
if (request.readyState == 4)
{
xmlDoc = GXml.parse(request.responseText);
var states = xmlDoc.documentElement.getElementsByTagName("state");
// read each line
for (var a = 0; a < states.length; a++)
{
// get any state attributes
var label = states[a].getAttribute("name");
var colour = states[a].getAttribute("colour");
// read each point on that line
var points = states[a].getElementsByTagName("point");
var stateoptions = document.getElementById("xmlStates");
var optn = document.createElement("OPTION");
optn.text = states[a].getAttribute("name");
optn.value = states[a].getAttribute("name");
stateoptions.options.add(optn);
}
}
}
request.send(null);
}
else {
alert("Sorry, the Google Maps API is not compatible with this browser");
}
}
function loadselectedpoint()
{
if(xmlDoc==null){alert('null');return;}
var state = document.getElementById("xmlStates").value;
var states = xmlDoc.documentElement.getElementsByTagName("state");
for (var a = 0; a < states.length; a++)
{
var label = states[a].getAttribute("name");
var colour = states[a].getAttribute("colour");
var points = states[a].getElementsByTagName("point");
if(states[a].getAttribute("name")==state)
{
var pts = [];
for (var i = 0; i < points.length; i++)
{
pts[i] = new GLatLng(parseFloat(points[i].getAttribute("lat")),
parseFloat(points[i].getAttribute("lng")));
}
var poly =
new GPolygon(pts,"#000000",1,1,colour,0.5,{clickable:true});
GEvent.addListener(poly,'click',function(point)
{
map.openInfoWindowHtml(point, "Polygon is clicked!!")
});
polys.push(poly);
map.clearOverlays();
map.addOverlay(poly);
}
}
}
//]]>
</script>
</head>
<body onload="load();" onunload="GUnload()" style="background-color: Transparent">
States :
<select id="xmlStates" onchange="loadselectedpoint()">
</select>
<br /><br />
<div id="map" style="width: 900px; height: 500px">
</div>
</body>
</html>
在上面的代码中,我创建了一个 **Select** 框,其中加载了所有州。选择一个 `state` 后,它将显示该 `state` 的整个边界。请看下面的演示
在上面的示例中,我使用了两个新类
- `GXmlHttp`:这个类是主要的 AJAX 调用类,它创建一个 `XMLHttpRequest` 对象并进行异步服务器调用。我使用这个类从外部 XML 文件加载点,该文件是异步调用并从服务器下载的。我使用这个文件加载标记以及加载 Select 控件。`OnReadyStateChanged` 是任何 `XMLHttpRequest` 对象的事件,当对象的状态更改时触发。当最后一个调用成功并且响应传输到 `responseText` 属性时,`Readystate` 的值为 `4`。
- `GXml`:这是 Google 提供的类,它使您能够在应用程序中解析 XML。我使用这个类来管理通过 AJAX 调用传入的 XML 数据。
- `GPolygon`:这个类用于在地图上创建叠加层。构造函数接受 7 个参数。第一个参数是点的数组,它们是 `GLatlng` 组合。第二个参数是边界颜色,第三个是边框粗细,第四个是边框颜色,第五个是边框不透明度,第六个是填充颜色,第七个是填充颜色不透明度。您还可以为 Polygon 生成单击事件。
示例 10:带最大化和关闭按钮的街景
最近,Google 地图增加了一个新功能,允许我们查看道路的实际街景。这真的很有趣。它已经在 maps.google.com 上存在了几个月,最终发布到了 API 中。
要调用地图中的 `streetview`,我们需要创建一个 `GStreetViewPanorama` 对象。`streetview` 以 Flash 对象加载地图,因此强烈建议在尝试 `StreetView` 之前安装最新版本的 Flash 播放器。代码如下
var street;
function initialize() {
var position = new GLatLng(42.345573,-71.098326);
var opt = { latlng:position,enableFullScreen: true };
street = new GStreetviewPanorama(document.getElementById("divp"), opt);
GEvent.addListener(divp, "error", handleNoFlash);
}
function handleNoFlash(errorCode) {
if (errorCode == FLASH_UNAVAILABLE) {
alert("Error: Flash doesn't appear to be supported by your browser");
else if (errorCode == NO_NEARBY_PANO) {
alert("Error : StreetView is Unavailable for current location");
}
return;
}
}
在代码中,我们通过传递一个 `div` 容器对象来创建一个 `GStreetViewPanorama` 对象,该容器将加载全景图。我们将 `Lat` / `Lon` 作为选项传递。`enableFullScreen` 决定是否向全景图显示最大化按钮。
如果您点击标记窗口中的链接,它将打开看起来像这样的 `Streetview`
如果您点击上面的图片,您可以看到该功能的在线演示。只需查看 View-Source 以了解完整的源代码,或者您可以下载本文档中附带的源代码。
在这里,我放置了一个带有链接的标记,用于显示选定点的 `StreetView`。您也可以使用右键单击上下文菜单来显示地图上任何点的 `StreetViewPanorama`。
注意:如果该点不在有 PANO 数据的道路上,`StreetViewPanorama` 将不会加载。您可以使用
var gstclient = new GStreetviewClient();
gstClient.getNearestPanoramaLatLng(new GLatLong(px,py), panoCallback));
function panoCallback(point){
//show panorama here.
}
因此,您可以使用 `panoCallback`,它接收离传入点最近的 `GLatLong` 点。
常见问题解答
各位,首先,我必须感谢大家,使这篇文章取得了巨大的成功。我每天收到你们的许多邮件,也很喜欢回复。我发现一些经常被问到的问题。我想和你们讨论一下,这样我就可以少回答你们的查询了。
1. 在示例 9 中,我在哪里可以找到绘制多边形的 XML 文件?
答案:实际上,XML 文件是通过 AJAX `XMLHttpRequest` 对象调用到服务器的。我已经将文件上传到了我的网站。请看
数据来自美国人口普查局的数据。如果您需要当前数据,您需要在此处登录并获取最新更改(当然,如果政府正式修改了他们的网站并进行最新更改)。
2. 如何根据美国的邮政编码获取区域?
答案:美国邮政编码数据也可以从各种来源获得。我基于邮政编码位置创建了一个人口普查数据数据库,这样您就可以轻松地使用该数据来创建我给您的示例 9 中的自定义边界。
3. 如何测量 2 个地理点之间的距离?
答案:要确定 2 个地理点之间的距离,可以使用两种方法。
第一种是获取 2 个地理点之间的实际距离,这可以使用大圆公式计算。我创建了一个 SQL Server 函数,它将为您提供一些关于如何计算此的思路
CREATE FUNCTION [dbo].[GETDISTANCE]
(
@FIRSTLAT DECIMAL(17,7),
@FIRSTLON DECIMAL(17,7),
@SECONDLAT DECIMAL(17,7),
@SECONDLON DECIMAL(17,7)
)
RETURNS varchar(100) AS
-- =============================================================================
-- Author: <Author, Abhishek Sur, Codeproject.COM.>
-- Create date: <Create Date,03/24/2008>
-- Description: <Description,Returns Distance between two GEO Points
-- on Great Circle>
-- =============================================================================
BEGIN
DECLARE
@LONDIFF float,@a Bigint,@b float,@f float,@U1 float,@U2 float,@sinU1 float,
@cosU1 float,@sinU2 float,@cosU2 float,@lambda float,
@lambdaP float,@iterLimit Int,@sinLambda float,@cosLambda float,
@sinSigma float,@cosSigma float,@sigma float,@alpha float,
@cosSqAlpha float,@cos2SigmaM float,@C float,@uSq float,@CAPA float,
@CAPB float,@deltaSigma float,@s float
if(abs(@FIRSTLAT) > 90 or abs(@FIRSTLON) > 180 or abs(@SECONDLAT) >90 or
abs(@SECONDLON) > 180)
return 'Not Valid Data'
if(@FIRSTLAT = @SECONDLAT and @FIRSTLON = @SECONDLON)
return '0 m'
-- CONVERT TO RADIAN
set @FIRSTLAT = (@FIRSTLAT * 3.14159265358979)/180
set @FIRSTLON = (@FIRSTLON * 3.14159265358979)/180
set @SECONDLAT = (@SECONDLAT * 3.14159265358979)/180
set @SECONDLON = (@SECONDLON * 3.14159265358979)/180
set @LONDIFF = @SECONDLON - @FIRSTLON
set @a = 6378137
set @b = 6356752.3142
set @f = 1/298.257223563
SET @U1 = atan((1-@f) * tan(@FIRSTLAT))
SET @U2 = atan((1-@f) * tan(@SECONDLAT))
SET @sinU1 = sin(@U1)
SET @cosU1 = cos(@U1)
SET @sinU2 = sin(@U2)
SET @cosU2 = cos(@U2)
SET @lambda = @LONDIFF
SET @lambdaP = 2 * PI()
SET @iterLimit = 20
while (abs(@lambda-@lambdaP) > 1.0E and @iterLimit > 0)
Begin
SET @iterLimit=@iterLimit-1
SET @sinLambda = sin(@lambda)
SET @cosLambda = cos(@lambda)
SET @sinSigma = sqrt((@cosU2 * @sinLambda) * (@cosU2*@sinLambda) +
(@cosU1*@sinU2-@sinU1*@cosU2*@cosLambda) * (@cosU1*@sinU2-@sinU1*@cosU2*@cosLambda))
SET @cosSigma = @sinU1*@sinU2 + @cosU1*@cosU2*@cosLambda
SET @sigma = atan(@sinSigma/@cosSigma)
SET @alpha = asin(@cosU1 * @cosU2 * @sinLambda / @sinSigma)
SET @cosSqAlpha = cos(@alpha) * cos(@alpha)
SET @cos2SigmaM = @cosSigma - 2*@sinU1*@sinU2/@cosSqAlpha
SET @C = @f/16*@cosSqAlpha*(4+@f*(4-3*@cosSqAlpha))
SET @lambdaP = @lambda
SET @lambda = @LONDIFF + (1-@C) * @f * sin(@alpha) *
(@sigma + @C * @sinSigma * (@cos2SigmaM+ @C* @cosSigma*(-1+2*@cos2SigmaM*@cos2SigmaM)))
END
if (@iterLimit=0)
return 'Not Valid Data' -- formula failed to converge
SET @uSq = @cosSqAlpha*(@a*@a-@b*@b)/(@b*@b)
SET @CAPA = 1 + @uSq/16384*(4096+@uSq*(-768+@uSq*(320-175*@uSq)))
SET @CAPB = @uSq/1024 * (256+@uSq*(-128+@uSq*(74-47*@uSq)))
SET @deltaSigma = @CAPB*@sinSigma*(@cos2SigmaM+@CAPB/4*(@cosSigma*
(-1+2*@cos2SigmaM*@cos2SigmaM) - @CAPB/6*@cos2SigmaM*
(-3+4*@sinSigma*@sinSigma)*(-3+4*@cos2SigmaM*@cos2SigmaM)))
SET @s = @b*@CAPA*(@sigma-@deltaSigma)
declare @dist float
declare @retval float
SET @dist = @s / 1000;
if (@dist < 1)
begin
set @retval = round(1000 * @dist,3)
--set @retval = @retval * 1.0936133
return Convert(varchar,(@retval)) + ' Metres'
end
else
begin
set @retval = round(1000 * @dist,3)/1000
set @retval = round(@retval * 0.621371192,3)
return CAST(@retval as varchar(12)) + ' Miles'
End
return '0 m'
End
您也可以使用客户端 JavaScript 来完成此操作。只需从这里获取逻辑。有关公式参考,您可以访问此链接。
其次,您可以使用 `GDirection` 功能来获取这两个点之间的实际步行距离。
var fromAddress = 'San Francisco';
var toAddress = 'Mountain View';
var gdir = new GDirections(map, document.getElementById("directions"));
GEvent.addListener(gdir, "load", onGDirectionsLoad);
GEvent.addListener(gdir, "error", handleErrors);
gdir.load("from: " + fromAddress + " to: " + toAddress,
{ "locale": "en-US" });
function handleErrors(){
if (gdir.getStatus().code == G_GEO_UNKNOWN_ADDRESS)
alert("Geo Address Not Found.\nError code: " + gdir.getStatus().code);
else if (gdir.getStatus().code == G_GEO_SERVER_ERROR)
alert("Server Error occurred.\n Error code: " + gdir.getStatus().code);
else if (gdir.getStatus().code == G_GEO_MISSING_QUERY)
alert("Missing Query.\n Error code: " + gdir.getStatus().code);
else if (gdir.getStatus().code == G_UNAVAILABLE_ADDRESS)
alert("Address Unavailable.\n Error code: " + gdir.getStatus().code);
else if (gdir.getStatus().code == G_GEO_BAD_KEY)
alert("Api Key not supported. \n Error code: " + gdir.getStatus().code);
else if (gdir.getStatus().code == G_GEO_BAD_REQUEST)
alert("Bad Request.\n Error code: " + gdir.getStatus().code);
else alert("An unknown error occurred.");
}
function onGDirectionsLoad(){
document.getElementById("getStatus").innerHTML = gdir.getStatus().code;
}
您可以根据您的需求使用其中任何一个。
4. 如何更改地图上的标记图标?
答案:您是否厌倦了相同的红色标记图标?如果是这样,您可以使用 `GIcon` 来更改标记的图标。
var new_icon = new GIcon();
new_icon.image = "http://yourserver.com/images/cross.png";
new_icon.size = new GSize(16,16);
new_icon.iconAnchor = new GPoint(8,9);
new_icon.infoWindowAnchor = new GPoint(7,7);
marker = new GMarker(point,{Icon:new_icon,draggable:false});
map.addOverlay( new_marker );
图标将被更改。您还可以使用 `marker.setImage(` `http://yourserver.com/images/cross.png` `')` 函数来更改标记图标的图像。
但请注意,`setImage` 不会更新 `GIcon` 的 `Shadow` 属性。
5. 如何在地图上叠加图像?
答案:显然,有一个选项可以生成带有自定义叠加图像的地图。让我们看看示例
function initialize() {
if (GBrowserIsCompatible()) {
var map = new GMap2(document.getElementById("map_canvas"));
map.setCenter(new GLatLng(40.740, -74.18), 12);
// ground overlay
var boundaries = new GLatLngBounds(new GLatLng(40.716216,-74.213393),
new GLatLng(40.765641,-74.139235));
var oldmap = new GGroundOverlay("http://imageserv.com/myimage.jpg", boundaries);
map.setUIToDefault();
map.addOverlay(oldmap);
}
}
这将图像叠加到提供的边界上。
6. 我可以使用美国的邮政编码绘制自定义多边形吗?
答案:我已经向您展示了如何使用 AJAX 根据数据绘制自定义多边形形状。您可以轻松找到提供美国邮政编码信息的数据库,并在地图上绘制形状。我上传了一个 SQL Server 数据库备份。您可以在这里找到。
下载文件。解压缩并还原到 SQL Server。您将在一个名为 `USZIPINFO` 的表中找到数据。表的架构是
`[countrycode], [postalcode],[placename],[state], [county],[community],[latitude], [longitude]`<br>`[accuracy]`
您可以使用此数据库按国家/地区获取美国邮政编码信息。
7. 在商业网站上使用 Google 地图的限制是什么?
答案:据我所知,Google 地图是一项免费服务,您可以在商业网站上免费使用它,前提是地图必须可以从任何地方免费访问。通过这句话,我的意思是地图应该在您输入正确的链接到地址栏后立即从您的网站上显示。地图不应隐藏在您网站的登录验证后面。如果您做其他事情,您可以使用Google Custom Enterprise 地图。
注意事项
您应该始终记住的要点
- 如果您看到类似“
API key is not correctly registered for that site
”的消息,您应该将 JavaScript 标签的 key 元素更改为有效的 key。您可以从此页面获取 key。 - 切勿使用 Google 地图显示非法内容。这可能侵犯权利。
- 对于企业解决方案,可能需要将地图隐藏在登录后面。在这种情况下,您应该为企业 Gmap 控件向 Google 付费。
历史
为各位创建地图示例真的很有趣。我试图将大部分基础知识放在这篇文章中,但还有很多内容需要补充。您可以将代码复制并粘贴到记事本中,生成您的 API 密钥,将其替换到您的 JavaScript 中,然后运行您的应用程序。
第二版:在此更新中,我添加了另一项功能以显示自定义上下文菜单。请查看最后一个示例。
第三版:2009 年 9 月 27 日:收到大量邮件后,我添加了一个 FAQ 部分来描述最常被问到的问题。
最新版:2009 年 12 月 2 日:添加了街景全景图示例。
参考文献
如需进一步阅读,您可以从以下开始
感谢您阅读我的应用程序。