@Rico
2015-08-10T20:15:02.000000Z
字数 16426
阅读 2900
OpenLayers
P书44- 72
格图层
In this chapter we will cover the following:
第44-50页讨论了如何加载GoogleMap和BingMap这里不翻译了。
P书50
1. Create an HTML file and add the OpenLayers dependencies.
2. Add a div element to hold the map, as follows:
<div id="ch2_wms_layer" style="width: 100%; height: 100%;"></div>
Chapter 2
51
3. Create the map instance as follows:
// Create the map using the specified DOM element
var map = new OpenLayers.Map("ch2_wms_layer");
4. Now, add two WMS layers. The first will be the base layer and the second will be an
overlay, as follows:
// Add a WMS layer
var wms = new OpenLayers.Layer.WMS("Basic",
"http://vmap0.tiles.osgeo.org/wms/vmap0",
{
layers: 'basic'
});
// Add Nexrad WMS layer
var nexrad = new OpenLayers.Layer.WMS("Nexrad",
"http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi",
{
layers: "nexrad-n0r",
transparent: "true",
format: 'image/png'
},
{
isBaseLayer: false
});
map.addLayers([wms, nexrad]);
5. Finally, we add a layer switcher control and center the view, as follows:
// Add layer switcher control
map.addControl(new OpenLayers.Control.LayerSwitcher());
// Set the center of the view
map.setCenter(new OpenLayers.LonLat(-90,40), 4);
OpenLayers.Layer.WMS类构造函数new OpenLayers.Layer.WMS(name, url, params, options)
属性:wrapDateLine
1. Create an HTML file and add the OpenLayers dependency.
2. In the beginning, we have put a checkbox to activate/deactivate the wrap data line
feature, as follows:
Wrap date line: <input dojoType="dijit.form.CheckBox" checked
onChange="wrapDateLine" /> <br/>
Do not worry about the dojoType="dijit.form.CheckBox"
attribute, it is because the Dojo Toolkit (http://dojotoolkit.org)
is used in the sample.
Think of it as a normal HTML input element.
3. Next, we have added the DOM element used to render the map, as follows:
<div id="ch2_wrapdataline" style="width: 100%; height: 100%;"></div>
Chapter 2
55
4. Within a script element, create the map instance, as follows:
<script type="text/javascript">
// Create the map using the specified DOM element
var map = new OpenLayers.Map("ch2_wrapdataline");
5. Now, create a WMS layer specifying the wrapDateLine property, as follows:
// Add a WMS layer
var wms = new OpenLayers.Layer.WMS("OpenLayers WMS Basic",
"http://labs.metacarta.com/wms/vmap0",
{
layers: 'basic'
},
{
wrapDateLine: true
});
map.addLayer(wms);
// Center map view
map.setCenter(new OpenLayers.LonLat(-110,0), 2);
6. Finally, implement the function that will change the wrapDateLine property value,
as follows:
function wrapDateLine(checked) {
wms.wrapDateLine = checked;
wms.redraw();
}
</script>
平移和缩放效果对于用户体验来说十分重要。
在不同层级之间进行缩放的效果是可以控制的。
OpenLayers.Layers类有一个transitionEffect属性,决定了图层缩放效果,目前只有两个值:null和resize
null意味着没有缩放效果,你缩放时将会看到原有图层消失然后渐渐地新层级的地图慢慢加载
当你使用resize时,目前层级的地图切片会重置大小去适应新层级,直到后台新层级的切片被加载。这种方式图片是一直可见的避免了缩放时短暂空隙时显示空白地图的丑陋效果 。
代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>HTML</title>
<style>
body,html{width:99%;height:99%}
</style>
<script type="text/javascript" src="../OL/OpenLayers.js" ></script>
<script type="text/javascript">
var map,wms;
function init(){
map=new OpenLayers.Map("map");
wms=new OpenLayers.Layer.WMS(
'OpenLayers WMS',
'http://vmap0.tiles.osgeo.org/wms/vmap0',
{layers:'basic'},
{
wrapDateLine:true,
transitionEffect:'resize'
}
);
map.addLayer(wms);
map.addControl(new OpenLayers.Control.LayerSwitcher({}));
map.setCenter(new OpenLayers.LonLat(0,0),3);
}
function change(){
var ifchecked=document.getElementById("chx").checked;
if(ifchecked){
wms.transitionEffect='resize';
}else{
wms.transitionEffect=null;
}
}
</script>
</head>
<body onload='init();' >
<input type="checkbox" id="chx" onChange="change()" value="按钮"/>
<div id="map" style=" z-index:0;left:0px;top:0px;height:500px;width:100%">
</div>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>HTML</title>
<style>
body,html{width:99%;height:99%}
</style>
<script type="text/javascript" src="../OL/OpenLayers.js" ></script>
<script type="text/javascript">
var map,wms,wms2;
function init(){
map=new OpenLayers.Map("map");
wms=new OpenLayers.Layer.WMS(
'OpenLayers WMS',
'http://vmap0.tiles.osgeo.org/wms/vmap0',
{layers:'basic'},
{
wrapDateLine:true,
transitionEffect:'resize'
}
);
wms2=new OpenLayers.Layer.WMS("Coast Line",
"http://vmap0.tiles.osgeo.org/wms/vmap0",
{layers: 'coastline_01,coastline_02'},
{isBaseLayer: false}
);
map.addLayer(wms);
map.addLayer(wms2);
map.addControl(new OpenLayers.Control.LayerSwitcher({}));
map.setCenter(new OpenLayers.LonLat(0,0),3);
}
var selectVal;
function changeopacity(){
var list=document.getElementById("selectOpa");
for(var i=0;i<list.length;i++){
if(list[i].selected==true){
selectVal=list[i].innerText;
wms2.setOpacity(selectVal/100);
}
}
}
</script>
</head>
<body onload='init();' >
<div >
<select name="selectAge" onChange="changeopacity()" id="selectOpa">
<option value="0">0</option>
<option value="20">20</option>
<option value="40">40</option>
<option value="60">60</option>
<option value="80">80</option>
<option value="100">100</option>
</select>
</div>
<div id="map" style=" z-index:0;left:0px;top:0px;height:500px;width:100%">
</div>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>HTML</title>
<style>
body,html{width:99%;height:99%}
</style>
<script type="text/javascript" src="../OL/OpenLayers.js" ></script>
<script type="text/javascript">
var map1,map2,wms1,wms2;
function init(){
var map1 = new OpenLayers.Map("wmslayer");
wms1 = new OpenLayers.Layer.WMS("Basic","http://vmap0.tiles.osgeo.org/wms/vmap0",{layers: 'basic'});
map1.addLayer(wms1);
map1.setCenter(new OpenLayers.LonLat(-90,0), 2);
var map2 = new OpenLayers.Map("signlelayer");
wms2 = new OpenLayers.Layer.WMS("Basic","http://vmap0.tiles.osgeo.org/wms/vmap0",{layers: 'basic'},{singleTile: true});
map2.addLayer(wms2);
map2.setCenter(new OpenLayers.LonLat(-90,0), 2);
}
</script>
</head>
<body onload='init();' >
<table style="width:100%;height:95%;">
<tr>
<td style="width:50%">
<p>WMS Layer:</p>
<div id="wmslayer" style="width:100%; height:100%"</div>
</td>
<td style="width:50%">
<p>WMS using <em>signleTile</em>property:</p>
<div id="signlelayer" style="width:100%;height:100%;"</div>
</td>
</tr>
</table>
</div>
</body>
</html>
Web Map Service(WMS)是一个地理地图服务协议
通常做法是客户端想WMS服务器请求,然后服务端返回一张包含所有信息的图片
OpenLayers中,你加了一个wms图层,WMS服务器会返回很多切片为每个层级使用,这种方法向服务端发出的请求不止一个。
把一个wms图层区分成很多切片不是唯一的方法,如果必须,你可以使用所谓单切片模式
这种模式下,仅仅只有一张图片会覆盖视图区域,而不是很多切片
每次当你移动地图或者缩放时图层必须被刷新
正如你说见,单切片模式下,请求服务器的次数远少于多切片模式。但与此相反的是,在多切片模式下,每个切片的请求都是很容易的,但是在单切片模式下,稍微有些不同,并且需要很长的计算时间
当你移动地图的时候,很多时候会看到空白(这意味着内容还没被载入)然后过一会儿图像会显示
在栅格grid图层和WMS单切片模式图层是,我们可以牺牲电脑性能和计算时间来提高这种用户体验
大多数栅格图层继承自OpenLayers.Layer.Grid,它会将每个层级分成很多切片
提高地图拖动时的效果很简单,就是在可见范围之外的地图在我们拖动之前就提前载入
下面的代码展示了如何预载入视图之外的地图的内容,grid图层和wms单切片模式同样适用,这样你就可以提高用户的友好度了。
原书代码:
1. Create an HTML file and include the OpenLayers dependencies.
2. We are going to create two maps side by side and on top of each one we are going
to add a spinner control, from the Dojo Toolkit framework (http://dojotoolkit.
org), to control the properties buffer and singleTile values:
<table style="width: 100%; height: 95%;">
<tr>
<td style="width: 50%;">
<p>
WMS layer with <em>buffer</em>:
<input id="buffer_a"
dojoType="dijit.form.NumberSpinner"
onChange="changeBufferA"
intermediateChanges="true"
style="width:100px"
value="0" smallDelta="1"
constraints="{min:0,max:5}" />
</p>
<div id="ch02_wms_buffer" style="width: 100%;
height: 100%;"></div>
</td>
<td style="width: 50%;">
<p>
WMS using <em>singleTile</em>
property and <em>ratio</em>:
<input id="buffer_b"
dojoType="dijit.form.NumberSpinner"
onChange="changeBufferB"
intermediateChanges="true"
style="width:100px"
value="1.0" smallDelta="0.1"
constraints="{min:0.0,max:2.0}" />
</p>
Chapter 2
65
<div id="ch02_wms_ratio" style="width: 100%;
height: 100%;"></div>
</td>
</tr>
</table>
3. The left-hand side panel will show how to control the number of tiles that can be
loaded outside the map view:
<script type="text/javascript">
// Create the map using the specified DOM element
var map_a = new OpenLayers.Map("ch02_wms_buffer");
// Add a WMS layer
var wms_a = new OpenLayers.Layer.WMS("Basic",
"http://vmap0.tiles.osgeo.org/wms/vmap0",
{
layers: 'basic'
},
{
buffer: 0
});
map_a.addLayer(wms_a);
// Set the center of the view
map_a.setCenter(new OpenLayers.LonLat(-90,0), 3);
4. The right-hand side panel shows how to control the amount of data you can preload
in a WMS layer working in single tile mode.
// Create the map using the specified DOM element
var map_b = new OpenLayers.Map("ch02_wms_ratio");
// Add a WMS layer
var wms_b = new OpenLayers.Layer.WMS("Basic",
"http://vmap0.tiles.osgeo.org/wms/vmap0",
{
layers: 'basic'
},
{
singleTile: true,
ratio: 1
});
map_b.addLayer(wms_b);
// Set the center of the view
map_b.setCenter(new OpenLayers.LonLat(-90,0), 3);
Adding Raster Layers
66
5. Finally, there is the code responsible for changes on the spinner controls, shown
as follows:
// Handle events
function changeBufferA(value) {
wms_a.addOptions({buffer: value});
}
function changeBufferB(value) {
map_b.removeLayer(wms_b);
wms_b.destroy();
wms_b = new OpenLayers.Layer.WMS("Basic",
"http:// vmap0.tiles.osgeo.org/wms/vmap0",
{
layers: 'basic'
},
{
singleTile: true,
ratio: value
});
map_b.addLayer(wms_b);
}
</script>
左边地图包含了一个默认模式的WMS图层,buffer属性来自基类OpenLayers.Layer.Gird具体指定了在地图外面需要预先载入多少切片
当用户改变buffer的值时,我们用以下代码来更新
function changeBufferA(value) {
wms_a.addOptions({buffer: value});
}
右边显示了如何控制大量数据来预载入当你使用单切片模式时。
// Create the map using the specified DOM element
var map_b = new OpenLayers.Map("ch02_wms_ratio");
// Add a WMS layer
var wms_b = new OpenLayers.Layer.WMS("Basic",
"http://vmap0.tiles.osgeo.org/wms/vmap0",
{
layers: 'basic'
},
{
singleTile: true,
ratio: 1
});
map_b.addLayer(wms_b);
// Set the center of the view
map_b.setCenter(new OpenLayers.LonLat(-90,0), 3);
最后,下面的代码显示了buffer值改变时map的变化
// Handle events
function changeBufferA(value) {
wms_a.addOptions({buffer: value});
}
function changeBufferB(value) {
map_b.removeLayer(wms_b);
wms_b.destroy();
wms_b = new OpenLayers.Layer.WMS("Basic",
"http:// vmap0.tiles.osgeo.org/wms/vmap0",
{
layers: 'basic'
},
{
singleTile: true,
ratio: value
});
map_b.addLayer(wms_b);
}
The left-hand side map contains a WMS layer working in the default tiled mode. In this mode,
the buffer property from the base class OpenLayers.Layer.Grid specifies how many
tiles must be loaded outside the map view.
When a user changes the spinner value for the buffer property, we simply update it with the
following line of code:
function changeBufferA(value) {
wms_a.addOptions({buffer: value});
}
The right-hand side map, on the other hand, has a WMS layer working in single tile mode
(see the singleTile property set to true). In this mode, only one request is made to
get an image, which fills the whole map view.
We can control the size of the image with the ratio property, which belongs to the
OpenLayers.Layer.WMS class. A ratio of value 1.0 means an image with exact
dimensions of the map view. By default the ratio value is 1.5, which means we are
requesting an image with the map view dimensions plus a half.
第三段翻译下:
我们能使用ratio(比率)属性控制图像大小,它是属于OpenLayers.Layer.WMS类的,1.0比率意味着图像大小和视图大小一样。默认的比率是1.5,意味着我们祈求的图像比视图大小多了0.5倍
本例中,比率在我们创建图层的时候就已经设定好了,当我们需要去更新它的时候我们需要删除原来的图层然后创建一个新的并伴随着新的值代码:
function changeBufferB(value) {
map_b.removeLayer(wms_b);
wms_b.destroy();
wms_b = new OpenLayers.Layer.WMS("Basic",
"http://vmap0.tiles.osgeo.org/wms/vmap0",
{
layers: 'basic'
},
{
singleTile: true,
ratio: value
});
map_b.addLayer(wms_b);
}
我们先移除了图层然后引用了
destroy()
方法来销毁layler使用的内部对象避免内存泄露
更多:(有点废话,不翻译了)
Remember, the more tiles we load the more requests to the server. The same goes for a
WMS layer in single tile mode; the greater the bounding box you request, the greater the
computation time on the server results.
Because of this, increasing the buffer or ratio values too much is not always the
best solution.
Think about your data and how the user will explore it. If your data is probably better to explore
in its extension—a great area in the same zoom level—then a buffer of one or two can be a
good idea. If your data is mainly zoomed but the user is not interested in exploring large areas,
then the default values are fine.
自己写的buffer的例子,把buffer设成了5,会发现拖动的时候旁边的图片早就有了。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>HTML</title>
<style>
body,html{width:99%;height:99%}
</style>
<script type="text/javascript" src="../OL/OpenLayers.js" ></script>
<script type="text/javascript">
var map;
function init(){
map=new OpenLayers.Map('map');
var wms=new OpenLayers.Layer.WMS(
'OpenLayers WMS',
'http://vmap0.tiles.osgeo.org/wms/vmap0',
{layers:'basic'},
{buffer:5}
);
map.addLayer(wms);
map.addControl(new OpenLayers.Control.LayerSwitcher({}));
if(!map.getCenter()){
map.zoomToMaxExtent();
}
}
</script>
</head>
<body onload='init();' >
<div id="map" style=" z-index:0;left:0px;top:0px;height:100%;width:100%">
</div>
</body>
</html>
有时候一个切片图层比如Google地图,OpenStreet地图或者WMS图层并不是你需要的。也有可能你有个张地理坐标图像,知道它的投影和范围,想把它展示在地图上 。
在这则例子里,OpenLayers提供了OpenLayers.Layer.Image
类,它可以让你创建一个基于一张简单图像的图层。
1. Let's go and create an HTML file with the OpenLayers dependencies.
2. First, add the div element that will hold the map, as follows:
<!-- Map DOM element -->
<div id="ch2_image" style="width: 100%; height: 100%;"></div>
3. Next, initialize the map and add a WMS base layer, as follows:
<!-- The magic comes here -->
<script type="text/javascript">
// Create the map using the specified DOM element
var map = new OpenLayers.Map("ch2_image", {
allOverlays: true
});
map.addControl(new OpenLayers.Control.LayerSwitcher());
// Add WMs layer
Chapter 2
69
var wms = new OpenLayers.Layer.WMS("OpenLayers WMS Basic",
"http://vmap0.tiles.osgeo.org/wms/vmap0",
{
layers: 'basic'
});
map.addLayer(wms);
4. Now, define the image URL, its extent and size, and create an image layer as follows:
// Add an Image layer
var img_url =
"http://localhost:8080/openlayers-cookbook/data/nexrad.png";
var img_extent = new OpenLayers.Bounds(-131.0888671875,
30.5419921875, -78.3544921875, 53.7451171875);
var img_size = new OpenLayers.Size(780, 480);
var image = new OpenLayers.Layer.Image("Image Layer", img_url,
img_extent, img_size, {
isBaseLayer: false,
alwaysInRange: true // Necessary to always draw the image
});
map.addLayer(image);
// Center the view
map.setCenter(new OpenLayers.LonLat(-85, 40), 3);
</script>
很简单,不翻译了:
name: This is the desired descriptive name for the layer
url: This is the URL for the image
extent: This is an instance of the OpenLayers.Bounds class with the bounding box of the image
size: This is an instance of the OpenLayers.Size with the image dimensions in
pixels
options: This indicates a JavaScript object with different options for the layer
OpenLayers.Layer.Grid类是一个特殊的类,它在不同缩放级别下划分图层,以格子切片来组成图层
OpenLayers.Layer.WMS类是之前那个类的子类,而且不仅能单切片模式,也可以多切片模式
当然,控制切片的大小会影响结果。
默认的,切片大小是256*256像素,但是我们可以设置它成任何我们想要的值。大切片尺寸意外着更小的请求,但是服务器需要更长的时间来生成大图片。相反,切片大小更小的话意味着更多的服务器请求和更小的计算时间
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>HTML</title>
<style>
body,html{width:99%;height:99%}
</style>
<script type="text/javascript" src="../OL/OpenLayers.js" ></script>
<script type="text/javascript">
var map;
function init(){
map=new OpenLayers.Map('map',{
allOverlays:true,
tileSize:new OpenLayers.Size(256,256)
});
var wms1=new OpenLayers.Layer.WMS(
'OpenLayers WMS',
'http://vmap0.tiles.osgeo.org/wms/vmap0',
{layers:'basic'}
);
map.addLayer(wms1);
var wms2=new OpenLayers.Layer.WMS("Coast Line",
"http://vmap0.tiles.osgeo.org/wms/vmap0",
{
layers:'coastline_01,coastline_02'
},
{
tileSize:new OpenLayers.Size(512,512),
opacity:0.65
});
map.addLayer(wms2);
map.addControl(new OpenLayers.Control.LayerSwitcher({}));
map.setCenter(new OpenLayers.LonLat(-85,40),3);
}
</script>
</head>
<body onload='init();' >
<div id="map" style=" z-index:0;left:0px;top:0px;height:100%;width:100%">
</div>
</body>
</html>
虽然像素大小不一样,但是在地图上确是贴合完全的。而256*256的图像请求数是19,而512*512图像请求书仅为9
There is not much mystery in this recipe. The tileSize property is available both for OpenLayers.Map and OpenLayers.Layer.Grid subclasses.
The tileSize must be an instance of OpenLayers.Size class, indicating the width and height in pixels.
When the tile size is set in the map instance all layers use this value unless you specify
another value for each individual layer.
By default, the OpenLayers.Map instance is configured to use 256 x 256 size tiles. Because
of this, the first layer makes requests to the WMS server using a tile size of 256 x 256 pixels.
On the other hand, we have specified a 512 x 512 tile size value for the second layer, so the
requests against the WMS are made waiting for tiles with 512 x 512 size.
For tiled services, such as Google Maps or OpenStreetMap, the tileSize property is simply
ignored because these services have precomputed the images in a fixed 256 x 256 size.
The reason for the tile size value being 256 x 256 pixels is because the size (in bytes) of each
image file is optimum for bandwidth use.