目录

上一个主题

7. 创建简单地图

下一个主题

7.2. 使用OpenLayers


7.1. 探索Google地图API

如果你从一开始就在读这本书,你可能还记得我们之前已经遇到过谷歌地图, 作为一个地图极客,几乎可以肯定你已经使用过谷歌地图。

web地图应用程序使用Google Maps API,这是一个JavaScript框架, 您可以将其合并到应用程序中来构建地图。Google Maps API允许您使用来自Google的数据集构建地图, 与使用Google应用程序时看到的相同。实际上,它还支持WMS标准, 从而使您能够从任何符合该标准的MapServer获取数据。我们将介绍几个使用Google Maps API版本3的示例, 以及如何合并GeoServer层。

让我们从一张非常简单的地图开始。

7.1.1. 操作时间–将地理服务器图层添加为覆盖

使用Google Maps API可以做的最常见的事情之一是使用它们的数据集作为基础地图, 并在基础地图上添加一个GeoServer层。

您将使用本章的示例代码,您可以从Packt发布网站下载该代码。

Google Maps API没有计算 BBOX 用于查询GeoServer的WMS服务器的参数。 因此,我们需要根据x和y坐标以及缩放级别自行计算:

1.下载后,必须在服务器上安装示例代码。我们可以使用Tomcat作为web服务器。 在 /webapps/ROOT Tomcat安装文件夹中的文件夹。

2.打开浏览器并指向 http://localhost:8080/chapter7/index.html .

3.该页面显示了到本章将使用的示例地图链接的列表。 我们将以一个简单的地图开始,该地图显示了Google底图,其上方是美国县图层。 单击 GeoServer as overlay 链接以打开地图:

image158

图 7.1 image158

4.地图包括标准导航工具。每次映射和/或缩放地图时,都会重新绘制地图, 将请求发送到Google服务器以获取基本地图,并发送到GeoServer以获取USA counties图层。

5.现在我们将探索代码。 打开 chapter7/google/geoserver_layer/ index.html 在您喜爱的文本编辑器中。 非常简单的HTML代码在第10行加载Google Maps API:

<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false&language=en"></script>

6.紧接着,加载另外三个JavaScript文件。 base.jsmaps.js 。 是所有Google示例的通用文件。 这个 base.js 文件包含地理服务器位置和要加载的图层的值; 如果使用不同的配置,则可以编辑这些值。这个 wms.js 文件包含一些实用函数。 这个 map.js 文件是我们地图的核心,我们将详细探索它:

<script type="text/javascript" src="../base.js"></script>
<script type="text/javascript" src="../wms.js"></script>
<script type="text/javascript" src="map.js"></script>

7.这个 body 标记只包含地图本身的占位符和对 初始化 函数,包含在 map.js 文件:

</head>
<body onload="mapinitialize();">
<div id="map"></div>
</body>

8.现在打开 map.js 文件。它包括 初始化 功能。我们将讨论相关部分。 在开头,您将找到一组参数的声明,这些参数将在对GeoServer的WMS请求中使用。 这个 透明的 参数使得可以在基础地图上覆盖GeoServer图层。 还要注意 SRS 将投影设置为Web Mercator值的参数,该值由Google Maps的数据集使用:

var wmsparams = [ "REQUEST=GetMap",
"SERVICE=WMS",
"VERSION=1.1.1",
"BGCOLOR=0xFFFFFF",
"TRANSPARENT=TRUE",
"SRS=EPSG:3857",
"WIDTH=255",
"HEIGHT=255",
"format=image/png"
];

9.在设置WMS之后,我们为Google Map设置了一些参数。 注意,我们将类型设置为 roadmap

var mapOptions = {
    zoom:4,
    center: new google.maps.LatLng(37.609066626725,-97.423977848479),
    mapTypeControl:false,
    draggableCursor: 'crosshair',
    mapTypeId:'roadmap',
    backgroundColor: "#badbff"
    }

10.现在我们创建 map 对象:

map = new google.maps.Map(document.getElementById("map"),mapOption s);

11.然后定义覆盖层的参数。 注意 GEOSERVERBASECountyLayer 以前设置的变量:

var overlayMaps =[
{{

    getTileUrlfunction(coord, zoom)
    {{
        var lULP = new google.maps.Point(coord.x*256,(coord.y+1)*256);
        var lLRP = new google.maps.Point((coord. x+1)*256,coord.y*256);
        var projectionMap = new MercatorProjection();
        var lULg = projectionMap.fromDivPixelToSphericalMercator(l
        ULP,zoom);
        var lLRg = projectionMap.fromDivPixelToSphericalMercator(        lLRP,zoom);
        var lUL_Latitude = lULg.y; var lUL_Longitude = lULg.x; var lLR_Latitude = lLRg.y; var lLR_Longitude = lLRg.x;
        if (lLR_Longitude < lUL_Longitude){{
        lLR_Longitude = Math.abs(lLR_Longitude);
    }

    return GEOSERVERBASE + "/geoserver/wms?" + wmsparams.join("&") + "&layers=" + CountyLayer + "&bbox=" + lUL_Longitude + "," + lUL_
    Latitude + "," + lLR_Longitude + "," + lLR_Latitude;

},

tileSize:new google.maps.Size(256,256),isPng:true,
maxzoom:15,
minzoom:4,
alt:'Counties'
}
];

12.最后,我们将所有覆盖层(本例中只有一个)添加到地图:

for (i=0; i<overlayMaps.length; i++){
var overlayMap = new google.maps.
ImageMapType(overlayMaps[i]);
map.overlymaptypes.push(overlymap);
map.overlayMapTypes.setAt(overlayMaps[i],overlayMap);
}

13.Once the map opens, zoom in to the San Francisco bay area: 我们对县级层使用了默认样式。尽管我们将其设置为 transparent ,但它隐藏了底图。 让我们使用不同的样式。返回示例地图主页,然后单击 GeoServer as transparent overlay 链接。 地图打开后,放大到“旧金山”海湾地区:

image159

图 7.2 image159

14.它是如何工作的?打开 map.js 文件内部 geoserver_transparent_layer 文件夹。 转到52号线。添加新参数, sld 成功了。使用它,我们可以引用外部sld来覆盖默认样式:

return GEOSERVERBASE + "/geoserver/wms?" + wmsparams.join("&")
+ "&layers=" + CountyLayer + "&bbox=" + lUL_Longitude + "," + lUL_Latitude + "," + lLR_Longitude + "," + lLR_Latitude + "&sld=" + GEOSERVERBASE + "/chapter7/google/geoserver_transparent_layer/counties.xml“;

刚刚发生了什么?

我们构建了一个基本的Google地图并计算了 bbox 用于查询GeoServer的WMS服务器的参数。 与本章中的其他示例一样,您将看到我们传递给GeoServer的WMS参数。 另一种方法是使用GeoServer反射器,它可以 x , y 和 zoom 参数而不是 bbox .

7.1.2. 操作时间–添加地理服务器层作为基础层

一种鲜为人知的方法允许您使用GeoServer层作为带有Google地图的基本层, 即使没有Google地图层。此示例显示如何将地理服务器图层用作基础图层:

1.打开浏览器并指向 http://localhost:8080/chapter7/index.html .

2.然后打开GeoServer作为基础层链接:

image160

图 7.3 image160

3.现在看看 map.js 文件。它与前面的示例非常相似,但在本例中,我们将创建 custommap 在创建 map 对象和覆盖:

//custom base layer options

var maptypeOptions = {{
getTileUrl:function(coord, zoom)
{
    var lULP = new google.maps.Point(coord.x*256,(coord.y+1)*256);
    var lLRP = new google.maps.Point((coord. x+1)*256,coord.y*256);
    var projectionMap = new MercatorProjection();
    var lULg = projectionMap.fromDivPixelToSphericalMercat or(lULP, zoom);
    var lLRg = projectionMap.fromDivPixelToSphericalMerca tor(lLRP, zoom);
    var lUL_Latitude = lULg.y; var lUL_Longitude = lULg.x; var lLR_Latitude = lLRg.y; var lLR_Longitude = lLRg.x;
    if (lLR_Longitude < lUL_Longitude){{
    lLR_Longitude = Math.abs(lLR_Longitude);
    }
    return GEOSERVERBASE + "/geoserver/wms?" + wmsparams. join("&") + "&layers=" + CountyLayer + "&bbox=" + lUL_Longitude + "," + lUL_Latitude + "," + lLR_Longitude + "," + lLR_Latitude;
}},

tileSize:new google.maps.Size(256,256),isPng:true,
maxzoom:15,
minzoom:4,
alt:''
}};

//Create a custom map with base layer options

var custommap = new google.maps.ImageMapType(maptypeOptions);
var mapOptions = {{
    zoom:4,
    center:new google.maps.LatLng(37.609066626725,-97.423977848479),
    mapTypeControl:false,
    draggableCursor: 'crosshair',
    mapTypeId:'mapid',
    backgroundColor: "#badbff"
    }}

//Create a google map using custom base layer

map = new google.maps.Map(document.getElementById("map"),mapOp tions);
map.mapTypes.set('mapid',custommap);
}} //end init

刚刚发生了什么?

您看到了一个使用Google将GeoServer图层用作基本图层的示例

地图API。通常你会指定 ImageMapType 属于 ROADMAPSATELLITEHYBRIDTERRAIN . 在我们的例子中,我们创建了自己的 ImageMapType 打电话 自定义映射 .

使用预先计算的地图

我们已经提到了 GeoWebCache 。它是集成在GeoServer中的缓存软件。 我们将详细报道第八章,性能和缓存. 现在我们来看看如何在Google地图中使用缓存层。

7.1.3. 操作时间–将GeoServer缓存层添加为覆盖层

添加GeoServer缓存层作为覆盖层与其他示例非常相似,但在本例中, 我们将使用GeoWebCache地址作为基本瓦片。我们还将使用 gmap 服务:

1.正常打开 chapter7/index.html 在你最喜欢的浏览器中。

2.使用GWC和 gmap 服务示例。

3.打开 /chapter7/google/geoserver_gwcgmap/index.html 和 /chapter7/google/geoserver_gwcgmap/map.js .

4.回顾 map.js 文件:

var map;
functionmapinitialize(){{
    //custom base layer options
    var maptypeOptions = {{
    getTileUrl:function(coord, zoom){{
    return GEOSERVERBASE + "/geoserver/gwc/service/gmaps" +
    "?layers=" + CountyLayer + "&zoom=" + zoom + "&x=" + coord.x + "&y=" + coord.y + "&format=image/png";
    }},

    tileSize:new google.maps.Size(256,256),isPng:true,
    maxzoom:15,
    minzoom:4,
    alt:''

}};

//Create a custom map with base layer options
var custommap = new google.maps.ImageMapType(maptypeOptions);
var mapOptions = {{
    zoom:4,
    center: new google.maps.LatLng(37.609066626725,-97.423977848479),
    mapTypeControl:false,
    draggableCursor: 'crosshair',
    mapTypeId:'mapid',
    backgroundColor: "#badbff"
}}

//Create a google map using custom base layer
map = new google.maps.Map(document.getElementById("map"),mapOp tions);
map.mapTypes.set('mapid',custommap);
}}
image161

图 7.4 image161

刚刚发生了什么?

正如我们在前面看到的 行动时间 部分,我们使用geowebacheuri来覆盖另一种访问层的方法。 这是您可能希望在高流量web应用程序上使用的方法。 好的一面是,您可以在投入生产时轻松地更改URL以指向 GeoWebCache 。

我们将在以后的章节中讨论 GeoWebCache 。 请记住,您也可以使用此地址通过WMS,因此也可以将其用于WMS查询。

7.1.4. 行动时间-定制Google basemap

Google Maps有很多细节,因此您可能需要创建一个自定义Google地图样式来覆盖GeoServer基本层:

1.正常打开 chapter7/index.html 在你最喜欢的浏览器中。

2.使用Google图层示例单击GeoServer基本图层。

3.正常打开 /chapter7/source/google/geoserver_baselayergooglelayer/index.html 和 /chapter7/source/google/geoserver_baselayergooglelayer/map.js .

4.回顾 map.js 文件:

Var map;
function mapinitialize(){{
var wmsparams = [
"REQUEST=GetMap",
"SERVICE=WMS",
"VERSION=1.1.1",
"BGCOLOR=0xFFFFFF",
"TRANSPARENT=TRUE",
"SRS=EPSG:3857",
"WIDTH=255",
"HEIGHT=255",
"format=image/png"
];

//custom base layer options var maptypeOptions = {{
getTileUrl:function(coord, zoom)
{{
    var lULP = new google.maps.Point(coord.x*256,(coord.y+1)*256);
    var lLRP = new google.maps.Point((coord. x+1)*256,coord.y*256);
    var projectionMap = new MercatorProjection();
    var lULg = projectionMap.fromDivPixelToSphericalMercat or(lULP, zoom);
    var lLRg = projectionMap.fromDivPixelToSphericalMerca tor(lLRP, zoom);
    var lUL_Latitude = lULg.y;
    var lUL_Longitude = lULg.x;
    var lLR_Latitude = lLRg.y;
    var lLR_Longitude = lLRg.x;
    if (lLR_Longitude < lUL_Longitude){{
    lLR_Longitude = Math.abs(lLR_Longitude);
}}

return GEOSERVERBASE + "/geoserver/wms?" + wmsparams.join("&") + "&layers=" + CountyLayer + "&bbox=" + lUL_Longitude +"," + lUL_Latitude + "," + LR_Longitude + "," + lLR_Latitude;
}},
tileSize:new google.maps.Size(256,256),isPng:true,
maxzoom:15,
minzoom:4,
alt:''
}};

//Create a custom map with base layer options
var custommap = new google.maps.ImageMapType(maptypeOptions);
var mapOptions = {{
zoom:4,
center: new google.maps.LatLng(37.609066626725,-97.423977848479), mapTypeControl:false,
draggableCursor: 'crosshair',
mapTypeId:'mapid',
backgroundColor: "#badbff"

}}

//Create a google map using custom base layer
map = new google.maps.Map(document.getElementById("map"),mapOp tions);
map.mapTypes.set('mapid',custommap);
//add all the custom overlays we want.
var overlayMaps =[
{
    // Google Roads layer

    getTileUrl: function(coord, z) {{
    var x = coord.x % (1 << z);
    var y = coord.y;
    return "http://mt0.google.com/vt/v=apt.116&hl=en-
    US&x="+ x + "&y=" + y + "&z=" + z +"&src=apiv3&s=G&lyrs=r&pistyle=s.t:33|p.v:off&apistyle=s.t:49
    }},
    tileSize:new google.maps.Size(256,256),
    isPng:false,
    maxzoom:18,
    name:“Roads”,
    alt:“Custom Roads”
    }}
];

//add all overlays to the map
for (i=0; i<overlayMaps.length; i++){{
    var overlayMap = new google.maps.ImageMapType(overlayMaps[i]);
    map.overlymaptypes.push(overlymap);
    map.overlayMapTypes.setAt(overlayMaps[i],overlayMap);
}}
image162.jpg

图 7.5 image162.jpg

刚刚发生了什么?

我们创建了一个自定义的谷歌地图覆盖使用谷歌地图样式的基础地理服务器地图。 当您放大地图时,将显示Google层。

这个附加的Drupal模块使用OpenLayers做同样的事情。 支票在外面 GitHub 项目 README.md 有关如何使用它的详细信息, 请访问https://github.com/brianyoungblood/google-map-styled。

创建一个定制的Google地图层

使用Google Maps API样式向导创建您自己的自定义Google地图层。 使用Firebug获取所需的URL参数( http://gmaps-samples-v3.googlecode.com/svn/trunk/styledmaps/wizard/index.html

与用户交互

发布漂亮的地图是网站的一个良好起点,但您可能希望与用户进行一些交互。 JavaScript和许多基于它构建的框架为您提供了许多定制界面和对用户操作作出反应的方法。 我们将在下一节中看到一个简短的例子。

7.1.5. 行动时间-拦截点击事件

如果要查询GeoServer的WMS,需要获取纬度和经度。您可以使用以下示例映射:

1.正常打开 chapter7/index.html 在你最喜欢的浏览器中。

2.选择 Google lat/lng on click event 示例.

3.打开 /chapter7/source/google/geoserver_latlonclickevent/index.html 和 /chapter7/source/google/geoserver_latlonclickevent/map. js .

4.回顾 map.js 文件:

Var map;
var geocoder;
var overlay;

function mapinitialize(){{
    //add all the overlays we want
    var overlayMaps =[
    {
    // Google Roads layer
    getTileUrl: function(coord, z) {
    var x = coord.x % (1 << z);
    var y = coord.y;
    return "http://mt0.google.com/vt/v=apt.116&hl=en-
    US&x="+ x + "&y=" + y + "&z=" + z + "&src=apiv3&s=G&lyrs=r&apistyle=s.t:33|p.v:off&apistyle=s.t:49|s.e:l|},
    tileSize: new google.maps.Size(256, 256),
    isPng: false,
    maxZoom: 18,
    name: "Roads",
    alt: "Custom Roads"
    }
    ];

//custom base layer options var maptypeOptions = {{
getTileUrl:function(coord, zoom){{
return GEOSERVERBASE + "/geoserver/gwc/service/gmaps"+
"?layers=" + CountyLayer +"&zoom=" + zoom + "&x=" + coord.x + "&y=" + coord.y + "&format=image/png";
}},
tileSize:new google.maps.Size(256,256),isPng:true,
maxZoom: 15,
minZoom: 4,
alt:‘’
};

//Create a custom map with base layer options
var custommap = new google.maps.ImageMapType(maptypeOptions);
var mapOptions = {{
    zoom:4,
    center: new google.maps.LatLng(37.609066626725,-97.423977848479), mapTypeControl:false,
    draggableCursor: 'crosshair',
    mapTypeId:'mapid',
    backgroundColor: "#badbff"

}}

//Create a google map using custom base layer
map = new google.maps.Map(document.getElementById("map"),mapOp tions);
map.mapTypes.set('mapid',custommap);
//need a overlay object to get the object being clicked on using the click listener. this is a google api v3 requirement

overlay = new google.maps.OverlayView();
overlay.draw = function() {{}}; overlay.setMap(map);
//end overlay object
//add all overlays to the map
for (i=0; i<overlayMaps.length; i++){
    var overlayMap = new google.maps.
    ImageMapType(overlayMaps[i]);
    map.overlymaptypes.push(overlymap);
    map.overlayMapTypes.setAt(overlayMaps[i],overlayMap);
}

//click listener
google.maps.event.addListener(map, 'click',
function(event) {
var point = overlay.getProjection().fromLatLngToContainerPixel(event.latLng);
alert("latlng: " + event.latLng + "npoint: " + point); }
);
image164

图 7.6 image164

刚刚发生了什么?

这里的关键是创建一个 覆盖 对象并调用 获取投影() 方法。 这是Google Maps API第3版的新功能。 这对于将纬度和经度发送到GeoServer以查询功能非常有用。