[关闭]
@Rico 2015-01-13T02:06:17.000000Z 字数 22817 阅读 3309

OpenLayerCookBook第三章翻译

OpenLayers


P73始

第三章矢量图层

在GIS中,一个真实的世界是由一系列事物所组成的。他可以是城市或者村庄,公路或者铁路,区域或者湖泊,国界等等。

每个要素都有一系列属性:人口,长度等等。视觉上由一些地理符号表示:点,线,面等等

矢量图层的基类是:OpenLayers.Layer.Vector类

OpenLayers.Layer.Vector类包含了一系列要素,例如:OpenLayers.Feature.Vector和OpenLayers.Feature

每个特征要素有一个attributes和OpenLayers.Geometry类实例与之关联

矢量图层它自己和每个特征要素有一个视觉样式与之关联,它将用来在地图上进行渲染

我们不仅仅需要在屏幕上展示,还需要考虑数据源。 OpenLayers提供了专门的类来读取很多源,协议,或者使用不同的格式:GML,KML,GeoJSON,GeoRSS中的特征要素。

矢量图层和一个OpenLayers.Protocol类或者OpenLayers.Strategy进行关联.第一个是用来通过一些HTTP或WFS协议来读写数据,第二个是用于控制任务的,例如什么时候去刷新数据,每次当图层被移动了等等。

P74-P79讲了如何加载一个GML图层和KML图层

P79

创建特征要素

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  5. <title>HTML</title>
  6. <style>
  7. body,html{width:99%;height:99%}
  8. </style>
  9. <script type="text/javascript" src="../OL/OpenLayers.js" ></script>
  10. <script type="text/javascript">
  11. var map,wms;
  12. function init(){
  13. map=new OpenLayers.Map("map");
  14. var wms=new OpenLayers.Layer.WMS(
  15. 'OpenLayers WMS',
  16. 'http://vmap0.tiles.osgeo.org/wms/vmap0',
  17. {layers:'basic'}
  18. );
  19. map.addLayer(wms);
  20. map.addControl(new OpenLayers.Control.LayerSwitcher());
  21. map.setCenter(new OpenLayers.LonLat(0,0), 2);
  22. var pointLayer=new OpenLayers.Layer.Vector("Points");
  23. var lineLayer=new OpenLayers.Layer.Vector("Lines");
  24. var polygonLayer=new OpenLayers.Layer.Vector("Polygon");
  25. map.addLayers([polygonLayer,lineLayer,pointLayer]);
  26. initializePointLayer();
  27. initializeLineLayer();
  28. initializePolygonLayer();
  29. function initializePointLayer() {
  30. var pointFeatures = [];
  31. for(var i=0; i< 50; i++) {
  32. var px = Math.random()*360-180;
  33. var py = Math.random()*180-90;
  34. var pointGeometry = new OpenLayers.Geometry.Point(px, py);
  35. var pointFeature = new OpenLayers.Feature.Vector(pointGeometry);
  36. pointFeatures.push(pointFeature);
  37. }
  38. pointLayer.addFeatures(pointFeatures);
  39. }
  40. function initializeLineLayer() {
  41. for(var j=0; j< 2; j++) {
  42. var pointGeometries = [];
  43. for(var i=0; i< 10; i++) {
  44. var px = Math.random()*240-120;
  45. var py = Math.random()*100-50;
  46. var pointGeometry = new
  47. OpenLayers.Geometry.Point(px, py);
  48. pointGeometries.push(pointGeometry);
  49. }
  50. var lineGeometry = new OpenLayers.Geometry.LineString(pointGeometries);
  51. var lineFeature = new OpenLayers.Feature.Vector(lineGeometry);
  52. lineLayer.addFeatures(lineFeature);
  53. }
  54. }
  55. function initializePolygonLayer() {
  56. for(var j=0; j< 2; j++) {
  57. var pointGeometries = [];
  58. for(var i=0; i< 5; i++) {
  59. var px = Math.random()*240-180;
  60. var py = Math.random()*100-90;
  61. var pointGeometry = new
  62. OpenLayers.Geometry.Point(px, py);
  63. pointGeometries.push(pointGeometry);
  64. }
  65. var linearGeometry = new OpenLayers.Geometry.
  66. LinearRing(pointGeometries);
  67. var polygonGeometry = new OpenLayers.
  68. Geometry.Polygon([linearGeometry]);
  69. var polygonFeature = new OpenLayers.
  70. Feature.Vector(polygonGeometry);
  71. polygonLayer.addFeatures(polygonFeature);
  72. }
  73. }
  74. }//init结束
  75. </script>
  76. </script>
  77. </head>
  78. <body onload='init();' >
  79. <div id="map" style=" z-index:0;left:0px;top:0px;height:100%;width:100%">
  80. </div>
  81. </body>
  82. </html>

在这则案例中,每个特征要素有一个几何点来描绘,因为我们必须先创建OpenLayers.Geometry.Point实例

记住,要在地图使用的投影中表达坐标,或者为矢量图层设定正确的坐标以便OpenLayers可以转换坐标。

一旦我们拥有了几何实例,我们可以通过传递需要的几何实例来创建一个新的OpenLayers.Feature.Vector实例

特征要素的样式我们会在另一章讲。

所以特征要素存储在一个数组中,当使用addFeature()方法时会传递给矢量图层

接下来我们创建线,几何对象叫做LineString , 当你需要使用LineString描述线时,你需要使用一个地理类实例叫做OpenLayers.Geometry.LineString,在以上实例代码中我们可以看到这个字符组成的线构造函数需要一个OpenLayers.Geometry.Point数组。

面是大几何用于展现洲或者国家。我们可以认为面是由起始点和终点相同的线组成的,并填充以一些颜色。但是注意,面可以是十分复杂的构造。

举个例子,想想一下一个有洞的面。这个案例中我们有两条线来描述内部和外部边缘,我们还必须制定哪部分是有颜色的。

以上例子中,我们通过传递由OpenLayers.Geometry.Point组成的数组创建了OpenLayers.Geometry.LineRing实例

一旦我们有了一个或多条线我们可以创建一个新的OpenLayers.Geometry.Polygon实例,

P86 讲了创建通过WKT要素略过

在地图上加mark点

在web地图应用中,标点被广泛应用。这允许我们通过展示一个图标在地图上快速定位POI

这个方法展示了如何通过加标点在我们的地图上通过使用OpenLayers.Marker 和OpenLayers.Layer.Markers类

代码:

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  5. <title>HTML</title>
  6. <style>
  7. body,html{width:99%;height:99%}
  8. </style>
  9. <script type="text/javascript" src="../OL/OpenLayers.js" ></script>
  10. <script type="text/javascript">
  11. var map,layer;
  12. function init(){
  13. map=new OpenLayers.Map("map");
  14. layer=new OpenLayers.Layer.OSM("OpenStreetMap");
  15. map.addLayer(layer);
  16. map.addControl(new OpenLayers.Control.LayerSwitcher());
  17. map.setCenter(new OpenLayers.LonLat(0,0), 3);
  18. var markers=new OpenLayers.Layer.Markers("Markers");
  19. map.addLayer(markers);
  20. // Create some random markers with random icons
  21. var icons = [
  22. // Here goes an array of image file names
  23. ];
  24. for(var i=0; i< 150; i++) {
  25. // Compute a random icon and lon/lat position.
  26. var icon = Math.floor(Math.random() * icons.length);
  27. var px = Math.random() * 360 - 180;
  28. var py = Math.random() * 170 - 85;
  29. // Create size, pixel and icon instances
  30. var size = new OpenLayers.Size(32, 37);
  31. var offset = new OpenLayers.Pixel(-(size.w/2),-size.h);
  32. var icon = new OpenLayers.Icon('blank.png', size, offset);
  33. icon.setOpacity(0.7);
  34. // Create a lonlat instance and transform it to
  35. // the map projection.
  36. var lonlat = new OpenLayers.LonLat(px, py);
  37. lonlat.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913"));
  38. // Add the marker
  39. var marker = new OpenLayers.Marker(lonlat, icon);
  40. // Event to handler when the mouse is over
  41. // Inflate the icon and change its opacity
  42. marker.events.register("mouseover", marker,
  43. function() {
  44. console.log("Over the marker "+this.id+"at place "+this.lonlat);
  45. this.inflate(1.2);
  46. this.setOpacity(1);
  47. });
  48. // Event to handler when the mouse is out
  49. // Inflate the icon and change its opacity
  50. marker.events.register("mouseout", marker,
  51. function() {
  52. console.log("Out the marker "+this.id+" at place "+this.lonlat);
  53. this.inflate(1/1.2);
  54. this.setOpacity(0.7);
  55. });
  56. markers.addMarker(marker);
  57. }
  58. }//init结束
  59. </script>
  60. </script>
  61. </head>
  62. <body onload='init();' >
  63. <div id="map" style=" z-index:0;left:0px;top:0px;height:100%;width:100%">
  64. </div>
  65. </body>
  66. </html>

效果:pic

每一个标点是OpenLayers.Layer.Markers类的实例表现。 每个标点有一个与之关联的点,它是由OpenLayers.LonLat类的实例和使用OpenLayers.Icon类的实例组成的。

一个图标需要的参数有:一个图形的url,大小(OpenLayers.Size)和偏移(OpenLayers.Pixel)

另外,每个图标我们注册了两个监听,一个是当鼠标移动到标点之上的时候和移出标点的时候,有了这种方式,我们可以修改标点的大小和透明度以便当鼠标选中的时候高亮

在监听函数中,我们使用了inflate()方法来改变图标的大小,并使用了setOpacity()方法来改变图标的透明度

更多:

The use of markers through the OpenLayers.Marker and OpenLayers.Layer.Markers
classes is not the only way we can show POIs in our maps.
As you can see in the Using point features as markers recipe, we can also use features to
show POIs as an alternative that can be improved by the use of strategies, formats, and so on.
In addition, OpenLayers offers some classes, such as OpenLayers.Layer.GeoRSS or
OpenLayers.Layer.Text, that create markers automatically from the GeoRSS and CSV
files respectively. They are relatively simple and are implemented for a specific usage and,
most probably, you will soon need more flexibility than offered by those classes.

使用点要素作为标点

显示标点不仅仅局限于使用OpenLayers.Mark和OpenLayers.Layer.Markers类

一个标点可以是POI,并且有图标和信息与之关联,比如一座山,一座桥等等。

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  5. <title>HTML</title>
  6. <style>
  7. body,html{width:99%;height:99%}
  8. </style>
  9. <script type="text/javascript" src="../OL/OpenLayers.js" ></script>
  10. <script type="text/javascript">
  11. var map,layer;
  12. function init(){
  13. map=new OpenLayers.Map("map");
  14. layer=new OpenLayers.Layer.OSM("OpenStreetMap");
  15. map.addLayer(layer);
  16. map.addControl(new OpenLayers.Control.LayerSwitcher());
  17. map.setCenter(new OpenLayers.LonLat(0,0), 3);
  18. var pointLayer=new OpenLayers.Layer.Vector("Features",{projection:"EPSG:933913"});
  19. map.addLayer(pointLayer);
  20. var pointFeatures = [];
  21. for(var i=0; i< 150; i++) {
  22. var px = Math.random() * 360 - 180;
  23. var py = Math.random() * 170 - 85;
  24. // Create a lonlat instance and transform it
  25. // to the map projection.
  26. var lonlat = new OpenLayers.LonLat(px, py);
  27. lonlat.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913"));
  28. var pointGeometry = new OpenLayers.Geometry.Point (lonlat.lon, lonlat.lat);
  29. var pointFeature = new OpenLayers.Feature.Vector(pointGeometry);
  30. pointFeatures.push(pointFeature);
  31. }
  32. // Add features to the layer
  33. pointLayer.addFeatures(pointFeatures);
  34. pointLayer.events.register("featureselected", null,
  35. function(event){
  36. var layer = event.feature.layer;
  37. event.feature.style = {fillColor: '#ff9900',fillOpacity: 0.7,strokeColor: '#aaa',pointRadius: 12};
  38. layer.drawFeature(event.feature);
  39. });
  40. // Event handler for feature unselected
  41. pointLayer.events.register("featureunselected", null,function(event){
  42. var layer = event.feature.layer;
  43. event.feature.style = null;
  44. event.feature.renderIntent = null;
  45. layer.drawFeature(event.feature);
  46. });
  47. // Add select feature control required to trigger events on the vector layer.
  48. var selectControl = new OpenLayers.Control.SelectFeature(pointLayer);
  49. map.addControl(selectControl);
  50. selectControl.activate();
  51. }//init结束
  52. </script>
  53. </script>
  54. </head>
  55. <body onload='init();' >
  56. <div id="map" style=" z-index:0;left:0px;top:0px;height:100%;width:100%">
  57. </div>
  58. </body>
  59. </html>

效果pic

和OpenLayers.Marker实例不同,我们是添加监听到矢量图层而不是添加监听到标点本身

在第七章我们将学习更多关于要素的样式和通过使用图像来提高视觉效果

一旦要素的样式改变了,我们可以使用drawFeature()方法来刷新地图上的要素样式

To allow the vector layer to trigger events, we need to attach a SelectFeature control to the
map, reference the vector layer, and activate it. Without it the listeners will never be invoked

增加popup

A common charecteristic of web mapping applications is the ability to show information
related to the features the map contains. By feature we mean any real phenomenon or
aspect we can visually represent with points, lines, polygons, and so on.
Of course we can select a feature, retrieve its associated information and show it anywhere
in our application layout, but the most common way to show it is by using popups

代码:

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  5. <title>HTML</title>
  6. <style>
  7. body,html{width:99%;height:99%}
  8. </style>
  9. <script type="text/javascript" src="../OL/OpenLayers.js" ></script>
  10. <script type="text/javascript">
  11. var map,layer;
  12. function init(){
  13. map=new OpenLayers.Map("map");
  14. layer=new OpenLayers.Layer.OSM("OpenStreetMap");
  15. map.addLayer(layer);
  16. map.addControl(new OpenLayers.Control.LayerSwitcher());
  17. map.setCenter(new OpenLayers.LonLat(0,0), 3);
  18. var pointLayer=new OpenLayers.Layer.Vector("Features",{projection:"EPSG:933913"});
  19. map.addLayer(pointLayer);
  20. var pointFeatures = [];
  21. for(var i=0; i< 150; i++) {
  22. var px = Math.random() * 360 - 180;
  23. var py = Math.random() * 170 - 85;
  24. // Create a lonlat instance and transform it
  25. // to the map projection.
  26. var lonlat = new OpenLayers.LonLat(px, py);
  27. lonlat.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913"));
  28. var pointGeometry = new OpenLayers.Geometry.Point (lonlat.lon, lonlat.lat);
  29. var pointFeature = new OpenLayers.Feature.Vector(pointGeometry,null, {pointRadius: 16,fillOpacity: 0.7,externalGraphic:'blank.png'});
  30. pointFeatures.push(pointFeature);
  31. }
  32. // Add features to the layer
  33. pointLayer.addFeatures(pointFeatures);
  34. // Add select feature control required to trigger events on the vector layer.
  35. var selectControl = new OpenLayers.Control.SelectFeature(pointLayer, {hover: true,onSelect: function(feature) {
  36. var layer = feature.layer;
  37. feature.style.fillOpacity = 1;
  38. feature.style.pointRadius = 20;
  39. layer.drawFeature(feature);
  40. var content = "<div><strong>Feature:</strong><br/>" + feature.id +"<br/><br/><strong>Location:</strong><br/>" + feature.geometry +"</div>";
  41. var popup = new OpenLayers.Popup.FramedCloud(feature.id+"_popup",feature.geometry.getBounds().getCenterLonLat(),new OpenLayers.Size(250, 100),content,null,false,null);
  42. feature.popup = popup;
  43. map.addPopup(popup);
  44. },onUnselect: function(feature) {var layer = feature.layer;
  45. feature.style.fillOpacity = 0.7;
  46. feature.style.pointRadius = 16;
  47. feature.renderIntent = null;
  48. layer.drawFeature(feature);
  49. map.removePopup(feature.popup);
  50. }
  51. });
  52. map.addControl(selectControl);
  53. selectControl.activate();
  54. }//init结束
  55. </script>
  56. </script>
  57. </head>
  58. <body onload='init();' >
  59. <div id="map" style=" z-index:0;left:0px;top:0px;height:100%;width:100%">
  60. </div>
  61. </body>
  62. </html>

效果图:pic

原理:

The first thing we did, after creating the vector layer, was the creation of some random point features.
Because we are computing random latitude and longitude values in decimal degrees
("EPSG:4326" projection), we need to translate it to the projection used by the map. In this case, because OpenStreetMap is the base layer, it applies an "EPSG:900913" projectionas the map's projection.

这里我们创建了默认样式的要素类,OpenLayers.Feature.Vector类的构造函数接受三个参数: 几何参数 它是强制的,必须的参数,另外两个可选的参数时要素的属性样式

要素类可以没有属性,所以我们可以传一个null值但是,我们有一个默认的样式来展示图标来代替默认的点

现在我们拥有了要素,是时候为我们选中的要素弹出漂亮的框来显示一些信息了

为了实现这个,我们使用SelectFeature控制器,给它一个图层,这个控制器允许使用者选择要素。

  1. var selectControl = new
  2. OpenLayers.Control.SelectFeature(pointLayer, {
  3. hover: true,
  4. onSelect: function(feature) { },
  5. onUnselect: function(feature) { }
  6. });

在以上代码中我们使用了三种选项:
hover: It indicates that the features must be selected or unselected without theneed of clicking on it, and by simply moving the mouse over the button

onSelect: This function is executed when a feature is selected. It receives the selected feature as an argument.

onUnselect: This function is executed when a feature is unselected. It receives the unselected feature as an argument.

现在我们来看看如何创建popup
有一点需要被指出的是popup是被加在地图上的。他们不是加载要素上的,也不是被加载图层上的。 所以显示或者隐藏popup,我们只需简单的通过addPopup()或者removePopup()从地图上加或者移除它

OpenLayers提供一些类作为popup来使用。但是他们都继承自基类OpenLayers.Popup
我们选择了OpenLayers.Popup.FrameCloud子类,它在视觉上比较好看。构造函数需要下面这个参数:
* id: A string that identifies the popup among all the popups that can exist, which are attached to the map
* lonlat: The location where the popup must appear
* contentSize: The dimensions of the popup, as an instance of the OpenLayers.
Size class
* contentHTML: The HTML string to be put as content
* anchor: An object where the popup will be anchored
* closeBox: Boolean indicating if the close buttons must be shown
* closeBoxCallback: A function that will be executed when the user clicks on the
close button

我们创建FrameCloud弹出框的代码是这样的:

  1. var popup = new OpenLayers.Popup.FramedCloud(
  2. feature.id+"_popup",feature.geometry.getBounds().getCenterLonLat(),
  3. new OpenLayers.Size(250, 100),
  4. content,null,false,null);

创建完之后我们把它加到地图上,使它自动可见

我们还存储了popup和要素之间的引用。通过这种方式,我们可以轻松的找到popup的引用,当这个要素不被选择的时候从地图上移除它

  1. feature.popup = popup;
  2. map.addPopup(popup);

addPopup()方法有第二个可选参数exclusive ,如果设置了它,会自动移除所有存在的popup当新的(popup?还是feature,应该是popup原书没写)被加入到地图上时

P100 Adding features from a WFS Server

添加来自WFS服务器的要素

web要素服务WFC是一个OGC标准,提供独立的平台来返回地理要素。在实际中,这意味着一个客户端向一个服务器发出一个WFS标准的HTTP请求并且得到一些列要素在GML中。

A nice introduction to WFS can be found in the tutorial about WFS available
at https://www.e-education.psu.edu/geog585/book/export/
html/1724. If you want to learn more about this, there is a complete
specification on the OGC site http://www.opengeospatial.org/
standards/wfs.

我们可以吧WFS看做另一个数据源

在继续之前,有一个重要的点需要我们来考虑。大多数OpenLayers发出的请求当数据被载入,比如说GML,KML或者GeoRSS文件,是通过OpenLayers.Request类异步发出的。

任何JavaScript请求被浏览器的安全模块所限制,这避免了跨域请求。这意味着你只能想同一个域来请求数据。

有很多不同的方法来避免这种局限。最简单的就是使用代理

You can read a clearer explanation at
http://developer.yahoo.com/javascript/howto-proxy.html

The idea of a proxy is simple, instead of making a request directly to a cross domain we make
a request to a script on the same domain, which is responsible for making the cross domain
request and returning the results.
A script, say PHP, Python, or Java servlet, is not limited by the cross domain requests. It is only
security imposed by the browser in the JavaScript calls.

OpenLayers offers a proxy implementation as a Python script that we can use in our
application. It can be found in the examples/proxy.cgi file in the source code bundle.
It is not the only possibility. For this recipe we will be using a PHP proxy file
(see the utils/proxy.php file in the book's source code) from the MapBuilder project

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  5. <title>HTML</title>
  6. <style>
  7. body,html{width:99%;height:99%}
  8. </style>
  9. <script type="text/javascript" src="../OL/OpenLayers.js" ></script>
  10. <script type="text/javascript">
  11. OpenLayers.ProxyHost="proxy.php";
  12. var map,layer;
  13. function init(){
  14. map=new OpenLayers.Map("map");
  15. layer=new OpenLayers.Layer.OSM("OpenStreetMap");
  16. map.addLayer(layer);
  17. map.addControl(new OpenLayers.Control.LayerSwitcher());
  18. map.setCenter(new OpenLayers.LonLat(0,0), 2);
  19. var statesLayer=new OpenLayers.Layer.Vector("States", {protocol: new OpenLayers.Protocol.WFS({
  20. url: "http://demo.opengeo.org/geoserver/wfs",
  21. featureType: "states",
  22. featureNS: "http://www.openplans.org/topp"
  23. }),strategies: [new OpenLayers.Strategy.BBOX()]
  24. });
  25. map.addLayer(statesLayer);
  26. }//init结束
  27. </script>
  28. </script>
  29. </head>
  30. <body onload='init();' >
  31. <div id="map" style=" z-index:0;left:0px;top:0px;height:100%;width:100%">
  32. </div>
  33. </body>
  34. </html>

The first important step is to set the OpenLayers.ProxyHost variable:
OpenLayers.ProxyHost = "./utils/proxy.php?url=";
Most of the JavaScript requests in OpenLayers are made through the helper class
OpenLayers.Request, which checks if the previous variable is set. If so, all requests
are made using the proxy.
After that, the main action in this recipe is the creation of a vector layer filling its data from a WFS server:

  1. var statesLayer = new OpenLayers.Layer.Vector("States", {
  2. protocol: new OpenLayers.Protocol.WFS({
  3. url: "http://demo.opengeo.org/geoserver/wfs",
  4. featureType: "states",
  5. featureNS: "http://www.openplans.org/topp"
  6. }),
  7. strategies: [new OpenLayers.Strategy.BBOX()]
  8. });

As you can see, the only thing to do is set the protocol to be used by the layer. In this case, we use an instance of the OpenLayers.Protocol.WFS class.
The WFS protocol constructor has many parameters but the most important ones are
as follows:
* url: The URL to the WFS server
* featureType: The feature to be queried
* featureNS: The namespace of the feature
Other important options and, more or less, the commonly used ones are as follows:
* geometryName: Specifies the name of the attribute that stores the feature's
geometry information. By default it is the_geom.
* srsName: The spatial reference system used in the requests. By default it is
"EPSG:4326".

Finally, the vector layer uses an OpenLayers.Strategy.BBOX strategy, which is responsible to refresh the content of the layer every time the map's viewport changes.
Many times the map server that supports WMS and WFS protocols, can serve the same
information both in raster and vector formats.
Imagine a set of regions stored in PostgreSQL/PostGIS and a map server, such as GeoServer, with a layer of countries configured to be served both as raster images via WMS requests, or as vector GML format using WFS requests.
In these cases, if we have previously created an OpenLayers.Layer.WMS layer, there is
an easy way to create a new WFS protocol instance with the static method OpenLayers.
Protocol.WFS.fromWMSLayer.
Given a WMS layer and some options, the method initializes an OpenLayers.Protocol.
WFS instance, supposing the WFS url, srsName, and other properties are the same as in the WMS instance.

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  5. <title>HTML</title>
  6. <style>
  7. body,html{width:99%;height:99%}
  8. </style>
  9. <script type="text/javascript" src="../OL/OpenLayers.js" ></script>
  10. <script type="text/javascript">
  11. var map,wms;
  12. function init(){
  13. map=new OpenLayers.Map("map");
  14. var wms=new OpenLayers.Layer.WMS(
  15. 'OpenLayers WMS',
  16. 'http://vmap0.tiles.osgeo.org/wms/vmap0',
  17. {layers:'basic'}
  18. );
  19. map.addLayer(wms);
  20. map.addControl(new OpenLayers.Control.LayerSwitcher());
  21. map.setCenter(new OpenLayers.LonLat(0,0), 2);
  22. var citiesLayer = new OpenLayers.Layer.Vector("WorldCities (GeoJSON)", {protocol: new OpenLayers.Protocol.HTTP({url: "world_cities.json",format: new OpenLayers.Format.GeoJSON()}),strategies: [new OpenLayers.Strategy.Fixed(),new OpenLayers.Strategy.Cluster({distance:15})]});
  23. map.addLayer(citiesLayer);
  24. }//init结束
  25. </script>
  26. </script>
  27. </head>
  28. <body onload='init();' >
  29. <div id="map" style=" z-index:0;left:0px;top:0px;height:100%;width:100%">
  30. </div>
  31. </body>
  32. </html>

效果:
pic
放大后:
pic

我们可以看到确实有聚合效果

一个矢量图层可以有多个策略与之关联。在上面的代码中我们家了OpenLayers.Strategy.Fixed策略,它只载入一次图层内容,OpenLayers.Strategy.Cluster策略,自动聚合要素来避免一大片恐怖难看的要素类互相覆盖

  1. strategies: [
  2. new OpenLayers.Strategy.Fixed(),
  3. new OpenLayers.Strategy.Cluster({distance: 15})
  4. ]

每次我们改变缩放大小,聚合就计算所有要素之间的距离并加载所有符合参数的要素类

OpenLayers有一些列基本但是普通的策略我们可以在矢量图层上应用他们。

We encourage those more advanced JavaScript readers, to take a close look at the
OpenLayers source code and learn more about how strategies work.

在WFC请求中过滤要素

P108

通过协议直接读取要素

OpenLayers允许我们从不同的源读取数据。OpenLayers提供了帮助类:protocols和formats

Protocols是设计用来简化从不同源取数据的比如HTTP WFS服务器等等。

formats是用来简化读取数据的。 从不同源头读取数据是很普遍的。知道如何直接的使用协议会简便很多

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  5. <title>HTML</title>
  6. <style>
  7. body,html{width:99%;height:99%}
  8. </style>
  9. <script type="text/javascript" src="../OL/OpenLayers.js" ></script>
  10. <script type="text/javascript">
  11. var map,layer;
  12. function init(){
  13. map=new OpenLayers.Map("map");
  14. layer=new OpenLayers.Layer.OSM("OpenStreetMap");
  15. map.addLayer(layer);
  16. map.addControl(new OpenLayers.Control.LayerSwitcher());
  17. map.setCenter(new OpenLayers.LonLat(0,0), 3);
  18. var vectorLayer = new OpenLayers.Layer.Vector("Vector Layer");
  19. map.addLayer(vectorLayer);
  20. // Create HTTP protocol to read GML file
  21. var gmlReq = new OpenLayers.Protocol.HTTP({
  22. url: "http://localhost:8080/s/world_cities.json",
  23. format: new OpenLayers.Format.GeoJSON(),
  24. callback: addFeaturesFromResponse
  25. });
  26. gmlReq.read();
  27. // Create HTTP protocol to read KML file
  28. var kmlReq = new OpenLayers.Protocol.HTTP({url: "http://localhost:8080/s/global_undersea.kml",format: new OpenLayers.Format.KML({extractStyles: true,extractAttributes: true}),callback: addFeaturesFromResponse});
  29. kmlReq.read();
  30. // Translate features from EPSG:4326 to OSM
  31. // projection and add to the layer only
  32. // the Point geometry features.
  33. function addFeaturesFromResponse(response) {
  34. for(var i=0; i<response.features.length; ++i) {
  35. if(response.features[i].geometry.CLASS_NAME =="OpenLayers.Geometry.Point") {response.features[i].geometry.transform(vectorLayer.projection,map.getProjectionObject());
  36. vectorLayer.addFeatures([response.features[i]]);
  37. }
  38. }
  39. }
  40. }//init结束
  41. </script>
  42. </script>
  43. </head>
  44. <body onload='init();' >
  45. <div id="map" style=" z-index:0;left:0px;top:0px;height:100%;width:100%">
  46. </div>
  47. </body>
  48. </html>

效果:pic

The goal of this recipe is to show how we can work directly with a protocol and load content from different data sources on the same vector layer.

我们创建了一个空的矢量图层,没有使用任何协议和策略 var vectorLayer = new OpenLayers.Layer.Vector("Vector Layer");

之后,我们创建了一个OpenLayers.Protocol.HTTP实例,这样就能读取远程的GeoJSON文件了。

  1. var gmlReq = new OpenLayers.Protocol.HTTP({
  2. url: "http://localhost:8080/openlayers-cookbook/recipes/data/world_cities.json",
  3. format: new OpenLayers.Format.GeoJSON(),
  4. callback: addFeaturesFromResponse
  5. });

注意我们是如何指定了一个回调函数这样我们就能在文件被载入并用特定的格式读取它之后调用它。这个方法接受一个类型为OpenLayers.Protocol.Response的参数,它包含一个从文件读取的要素(features)数组

要使读取协议的进程开始我们只需要调用gmlReq.read();即可

最后,我们来看一下回调函数。这个方法会在协议结束读取之后被触发。我们把要素的坐标系转到正确的坐标系然后加在矢量图层上面

  1. function addFeaturesFromResponse(response) {
  2. for(var i=0; i<response.features.length; ++i) {
  3. if(response.features[i].geometry.CLASS_NAME =="OpenLayers.Geometry.Point") {
  4. response.features[i].geometry.transform(vectorLayer.projection, map.getProjectionObject());
  5. vectorLayer.addFeatures([response.features[i]]);
  6. }
  7. }
  8. }

我们可以看到,这里有另一种筛选内容的方法,但是我们是在客户端过滤的而不是在服务端。这意味着数据被完整的传输了过来。

We would like to mention that in this recipe we do not set the OpenLayers.ProxyHost variable. This is because the files we are requesting via AJAX are in the same domain the HTML file is loaded from.

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注