一、概述
在OpenLayers中,地图必须具有一个缩放级别的范围,缩放级别可以用比例尺(scale)或者分辨率(resolution)表示。
比例尺——屏幕上1米代表多少地图坐标单位;分辨率——屏幕上一个像素代表多少地图坐标单位。
两者的转换关系是:scale = resolution * 72 * 39.3701(1米=39.3701英寸,1英寸=72像素)
地图具有一个总的缩放级别,每个图层可以有各自的缩放级别,这样可以控制图层只在合适的级别上显示。
二、缩放级别范围的确定方法
1、比例尺数组或者分辨率数组来确定(相邻两级之间不一定是2倍的关系,可以是任意值)。示例:
resolutions: [1.40625,0.703125,0.3515625,0.17578125,0.087890625,0.0439453125]
scales: [50000000, 30000000, 10000000, 5000000]
2、用最大分辨率(maxResolution)和缩放级别总数(numZoomLevels)确定,相邻两级是2倍关系
2.1最大分辨率的确定方法:
a. 直接指定maxResolution,例如:
maxResolution: 0.17578125
b. 直接指定minScale,例如:
c. 由maxExtent确定(maxResolution需设置为‘auto’),例如:
maxExtent: new OpenLayers.Bounds(-180, -90, 180, 90),
maxResolution: "auto"
2.2 缩放级别总数的确定方法:
a. 直接指定numZoomLevels,例如:numZoomLevels: 5
b. 由最大分辨率和最小分辨率的比值确定,最小分辨率同2.1有三种方法可以确定:
b.1 直接指定minResolution
b.2 直接指定maxScale
b.3 由minExtent确定(minResolution需设置为‘auto’)
如果指定的参数过多,导致缩放级别范围不一致时,上述方法顺序决定了OpenLayers确定缩放级别范围的优先级。
最近看OpenLayers,研究到地图投影时找到官方的文档,就翻译了一下,由于英文能力差,翻译不好的地方,请看原文
原文地址:http://docs.openlayers.org/library/spherical_mercator.html
球面墨卡托投影
该文档说明了什么是球面墨卡托投影以及何时使用该投影。文档中包含一些必要的背景知识、商用图层的代码演示、添加WMS图层以及使用OpenLayers进行投影变换的内容。要求读者对投影变换和OpenLayers有一个基本的了解。
球面墨卡托投影在OpenLayers community版本和其他OSG community版本中都有使用。Google Maps,微软Virtual Earth,Yahoo Maps和其他商业地图API的提供者都使用该投影。
该投影是将地球当作一个球体而不是椭球体,然后应用墨卡托投影的方法,将地图投影到一个地图平面上。
为了正确的在商业地图API上叠加地图数据,就必须使用该投影。最基本的是在商业地图API上显示栅格瓦片地图——例如TMS,WMS以及其他类似的瓦片。
为了更好的使用商业地图API,基于Google Maps的数据生成人员也需要使用该投影。最基本的例如OpenStreetMap,栅格地图瓦片都是使用的“球面墨卡托投影”。
GIS中,通常用“EPSG”的代码来表示一种地图投影。最常用的“EPSG:4326”,在地图上将经纬度直接当作X /Y对待。球面墨卡托投影在官方指定的代码为EPSG:3785。但是在官方发布之前,很多软件已经使用了EPSG:900931代码来表示该投影,OpenLayers仍然使用这个非官方的代码。看到“EPSG:4326”字符,就是经纬度坐标的描述,看到“EPSG:900931”则是用“米”做单位的x/y坐标的描述。
首先我们创建一个使用球面墨卡托投影的地图。在这里我们使用基于微软Virtual Earth API的地图。以下的HTML代码将在地图中用到。
1 <html>
2 <head>
3 <title>OpenLayers Example</title>
4 <script src='http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.1'></script>
5 <script src="http://openlayers.org/api/OpenLayers.js%22%3E%3C/script>
6 </head>
7 <body>
8 <div style="width:100%; height:100%" id="map"></div>
9 <script defer='defer' type='text/javascript'>
10 // Code goes here
11 </script>
12 </body>
13 </html>
就下来添加Virtual Earth图层作为地图的基础图层
1 var map = new OpenLayers.Map('map');
2 var layer = new OpenLayers.Layer.VirtualEarth("Virtual Earth",
3 {
4 sphericalMercator: true,
5 maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34)
6 });
7 map.addLayer(layer);
8 map.zoomToMaxExtent();
这样就创建了一副地图。像这样的地图,应该着重注意:setCenter不能再使用经纬度坐标,而应该是投影以后以“米”为单位的坐标。你可以拖动该地图,但是如果你不理解球面墨卡托投影,接下来做任何功能都将非常困难。
该地图的maxResolution根据一些默认值进行计算,通常球面墨卡托投影的地图范围是经度-180~180,纬度-85.0511~85.0511,这是因为墨卡托投影两极将变形到无穷远处,必须排除掉北极和南极区域,剩下的区域投影后正好是一个正方形,投影后的范围是从 -20037508.34到20037508.34。
地图的maxResolution默认值的计算方法是:将该范围匹配在边长为256像素的图片上,结果maxResolution的值就是156543.0339。在图层中默认的就是该值,不需要通过图层options来设置了。
如果将球面墨卡托投影的WMS或者TMS图层作为一个单独的图层,需要指定图层的maxResolution属性,另外还需要定义该图层的maxExtent。
OpenLayers提供了在客户端进行投影变换的工具,可以将经纬度坐标转换为球面墨卡托坐标。文档中首先在setCenter或者其他函数中需要使用坐标转换,接着演示如何通过使用map的displayProjection选项来将地图的坐标系显示为其他的投影坐标。
首先创建一个投影对象作为默认的投影,标准的经纬度投影的字符串是“EPSG:4326”——基于WGS84的参考椭球面(如果你的数据和Google Maps匹配很准,就是这种投影)。
接着创建一个对象保存你的坐标,然后转换
var proj = new OpenLayers.Projection("EPSG:4326");
var point = new OpenLayers.LonLat(-71, 42);
point.transform(proj, map.getProjectionObject());
该点已经转换为球面墨卡托投影坐标,你可以传递给map的setCenter方法:
也可以直接在setCenter中调用:
var proj = new OpenLayers.Projection("EPSG:4326");
var point = new OpenLayers.LonLat(-71, 42);
map.setCenter(point.transform(proj, map.getProjectionObject()));
通过这种方法,可以使用经纬度坐标来设置地图中心。
还可以使用相同的方法来投影变换OpenLayers.Bounds对象:同样用Bounds对象的transfrom方法:
var bounds = new OpenLayers.Bounds(-74.047185, 40.679648, -73.907005, 40.882078)
bounds.transform(proj, map.getProjectionObject());
坐标变换后替换掉原来的对象,因此不需要重新定义一个变量。
Geometry对象和LonLat与Bounds对象一样拥有坐标转换方法。在你的应用程序代码中创建的geometry对象添加到图层上之前,应该先进行坐标转换,同样从图层获取得到的geometry对象在别的地方使用,也需要坐标转换。
由于所有的坐标转换都是更新对象自身,所以想添加一个geometry到图层上,不应该直接调用转换方法,而是克隆一个geometry对象后再调用:
var feature = vector_layer.features[0];
var geometry = feature.geometry.clone();
geometry.transform(layerProj, targetProj);
创建一副带投影的地图后,很可能需要将矢量数据进行投影变换然后添加到基础地图上,完成这个工作,只需要简单的设置好矢量数据的投影,并确定地图的投影就可以了。
var map = new OpenLayers.Map("map", {
projection: new OpenLayers.Projection("EPSG:900913")
});
var myBaseLayer = new OpenLayers.Layer.Google("Google",
{'sphericalMercator': true,
'maxExtent': new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34)
});
map.addLayer(myBaseLayer);
var myGML = new OpenLayers.Layer.GML("GML", "mygml.gml", {
projection: new OpenLayers.Projection("EPSG:4326")
});
map.addLayer(myGML);
可以使用该方法加载任何OpenLayers支持格式的矢量数据,包括WKT,GeoJSON,KML和其他一些格式,在GML图层上指定format选项。
var geojson = new OpenLayers.Layer.GML("GeoJSON", "geo.json", {
projection: new OpenLayers.Projection("EPSG:4326"),
format: OpenLayers.Format.GeoJSON
});
map.addLayer(geojson);
设置了图层的投影属性后,如果手动添加features到图层上(比如调用layer.addFeatures),在添加到图层上之前必须进行坐标转换。
OpenLayers中矢量数据序列化的方法是将矢量图层上获取数据集合传递给格式化类写数据。在一个具有投影的地图中,我们获取到的数据是已经投影变换过的,为了进行数据转换,需要使用内部投影和外部投影两个参数给格式化类,然后再用格式化类序列化数据。
var format = new OpenLayers.Format.GeoJSON({
'internalProjection': new OpenLayers.Projection("EPSG:900913"),
'externalProjection': new OpenLayers.Projection("EPSG:4326")
});
var jsonstring = format.write(vector_layer.features);
有些控件可以将地图坐标显示给用户,有的直接显示,有的包含在超链接中。MousePosition和Permalink控件(包括ArgParser控件)都是用地图所使用地图投影坐标——也就是球面墨卡托坐标。为了避免用户混淆不清,OpenLayers可以通过displayProjection设置控件的坐标系,将地图坐标系转换为显示坐标系。
要使用这一功能,在创建地图时需要指定projection和displayProjection选项,控件将自动选择这些选项的设置。
var map = new OpenLayers.Map("map", {
projection: new OpenLayers.Projection("EPSG:900913"),
displayProjection: new OpenLayers.Projection("EPSG:4326")
});
map.addControl(new OpenLayers.Control.Permalink());
map.addControl(new OpenLayers.Control.MousePosition());
这样你就可以正常加载地图了。
球面墨卡托投影如此重要的一个原因是只有这种投影能让你将图片地图正确的叠加到类似于Google Maps这样的商业图层上。在浏览器是使用栅格地图,在一个瘦GIS客户端是不可能对图片进行重新投影,只能是所有的图片使用同样的投影。
如何生成球面墨卡托投影的瓦片地图取决于你使用什么软件来创建地图图片。MapServer的使用包含在此文档中。
MapServer采用proj.4来支持地图投影。为了转换为球面墨卡托投影,需要在proj.4的data目录下添加投影定义。
Linux环境下,打开/usr/share/proj/epsg文件,在文件尾部添加一行:
<900913> +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs
然后在地图文件中添加投影在wms_srs元数据中:
map
web
metadata
wms_srs "EPSG:4326 EPSG:900913"
end
end
# Layers go here
end
这样就可以通过MapServer的WMS服务请求使用球面墨卡托投影的瓦片地图,通过OpenLayers很好的和商业数据匹配。
var options = {
projection: new OpenLayers.Projection("EPSG:900913"),
units: "m",
maxResolution: 156543.0339,
maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34,
20037508.34, 20037508.34)
};
map = new OpenLayers.Map('map', options);
// create Google Mercator layers
var gmap = new OpenLayers.Layer.Google(
"Google Streets",
{'sphericalMercator': true,
'maxExtent': new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34)
}
);
// create WMS layer
var wms = new OpenLayers.Layer.WMS(
"World Map",
"http://vmap0.tiles.osgeo.org/wms/vmap0",
{'layers': 'basic', 'transparent': true}
);
map.addLayers(gmap, wms);
WMS图层自动继承地图基础图层的投影,所以不需要在图层中设置投影选项。
最新版的GeoServer已经支持EPSG:900913,因此不需要额外添加投影。把GeoServer的图层作为WMS添加到地图上即可。
另一个使用球面墨卡托投影的场合是加载自定义的瓦片地图。很多瓦片使用和Google Maps一样的投影,而且是使用同样的z/x/y语法来访问瓦片。
如果你的瓦片是依照Google的瓦片编码规则(从世界的左上角开始,按照x,y,z编码),通过简单的修改get_url函数,就可以用TMS图层来加载这些瓦片。
首先定义getURL函数:允许接受bounds作为参数,然后按照以下方法编写:
function get_my_url (bounds) {
var res = this.map.getResolution();
var x = Math.round ((bounds.left - this.maxExtent.left) / (res * this.tileSize.w));
var y = Math.round ((this.maxExtent.top - bounds.top) / (res * this.tileSize.h));
var z = this.map.getZoom();
var path = z + "/" + x + "/" + y + "." + this.type;
var url = this.url;
if (url instanceof Array) {
url = this.selectUrl(path, url);
}
return url + path;
}
然后,创建TMS图层,传入一个选项告诉图层自定义瓦片的加载函数是什么:
new OpenLayers.Layer.TMS("Name",
"http://example.com/",
{ 'type':'png', 'getURL':get_my_url });
自己编写的函数将覆盖getURL函数,请求自己的瓦片来代替标准的TMS瓦片。
这样做,你的地图选项还需要包含和Google Maps一样的maxExtent和maxResolution。
new OpenLayers.Map("map", {
maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),
numZoomLevels:18,
maxResolution:156543.0339,
units:'m',
projection: "EPSG:900913",
displayProjection: new OpenLayers.Projection("EPSG:4326")
});
球面墨卡托投影在OpenLayers中使用代码EPSG:900913,很多其他的服务比如OpenStreetMap, Bing和Yahoo也用同样的投影,但并不一定要用EPSG:900913代码,一些其他的代码比如EPSG:3857 和EPSG:102113也在使用。现在官方统一规定了代码EPSG:3857来代替EPSG:900913(http://www.epsg-registry.org/export.htm?gml=urn:ogc:def:crs:EPSG::3857)。因此,如果你想合并OpenLayers球面墨卡托投影的叠加图层,不管该图层使用的是其他代码还是官方的代码,你必须确保OpenLayers请求的是EPSG:3857或者别的代码而不是EPSG:900913。在加载一个图层到地图上之前,重写图层的投影来完成这些工作。代码如下:
// set transformation functions from/to alias projection
OpenLayers.Projection.addTransform("EPSG:4326", "EPSG:3857", OpenLayers.Layer.SphericalMercator.projectForward);
OpenLayers.Projection.addTransform("EPSG:3857", "EPSG:4326", OpenLayers.Layer.SphericalMercator.projectInverse);
// create sphericalmercator layers
var googleLayer = new OpenLayers.Layer.Google("Google", {"sphericalMercator": true});
var osmLayer = new OpenLayers.Layer.OSM("OpenStreetMap");
// override default epsg code
aliasproj = new OpenLayers.Projection("EPSG:3857");
googleLayer.projection = osmLayer.projection = aliasproj;
//add baselayers to map
map.addLayers([googleLayer, osmLayer]);
这样,叠加图层(例如WMS图层)将使用3857代码,并在4326和3857之间完成坐标变换
相关推荐
可以通过在构造函数中设置 options 属性来配置 OpenLayers layer 的缩放级别。 正常图层的缩放级别配置 对于基于 OpenLayers.layer 的正常 layer,存在多种不同的方式去配置缩放级别和他们各自的比例尺和解析度。...
在IT行业中,前端开发是构建Web应用程序的关键部分,而OpenLayers是一个流行的JavaScript库,用于创建交互式的、基于Web的地图应用。本实例将详细介绍如何利用OpenLayers加载离线地图,并通过mui将其打包成移动应用...
设置地图的视口、中心点和初始缩放级别。 3. **DEMO中的代码结构**: - HTML: 包含地图容器div和可能的控制按钮。 - CSS: 用于样式调整,确保地图可以正确显示在页面上。 - JavaScript: 这是核心部分,包含了...
创建`ol.Map`实例,并设置视图的中心点和缩放级别。例如: ```javascript var map = new ol.Map({ layers: [baiduLayer], target: 'map', view: new ol.View({ center: [116.404, 39.915], zoom: 10 }) })...
4. 设置地图初始视图:通过设置中心点坐标和缩放级别,设置地图的初始显示状态。 5. 添加图层到地图:将创建的天地图图层添加到地图实例中,通过调用map.addLayer()方法实现。 6. 可选:扩展功能,如图层切换器:...
zoom: 4, // 初始缩放级别 projection: projection // 设置投影 }) }); // 定义天地图WMTS服务的配置 var tiandituUrl = 'http://t0.tianditu.gov.cn/vec_c/wmts?'; var tiandituParams = { service: 'WMTS', ...
- **地图操作**:如`map.getView().setCenter()`改变中心点,`map.getView().setZoom()`调整缩放级别。 - **图层操作**:`layer.setVisible(true/false)`切换图层显示状态,`source.addFeature(feature)`添加矢量...
2. **创建地图实例**:在JavaScript文件(如app.js)中,初始化OpenLayers地图实例,设置地图容器、视图和投影。 ```javascript var map = new ol.Map({ target: 'map', view: new ol.View({ center: [116.404, ...
接下来,我们将创建一个OpenLayers地图实例,并定义用于显示图片的图层。以下是一个基本示例: ```javascript var map = new ol.Map({ target: 'map', // 指定地图容器的HTML元素ID view: new ol.View({ center:...
4. **视图设置**:设置地图的初始视图,包括中心位置和缩放级别。对于中国地区,初始位置可能是中国的经纬度坐标,而缩放级别则根据需求设定。 5. **事件监听**:可以添加事件监听器来响应用户的交互,例如点击地图...
"OpenLayers中地图缩放级别的设置方法 - 心帆 - 博客园.url"则关注于地图的缩放功能。在OpenLayers中,用户可以通过调整缩放级别来改变地图的细节层次,这涉及到比例尺和分辨率的概念。教程可能详细解释了如何设定...
7. **调整视图**:如果需要,可以进一步调整地图视图,例如定位特定坐标或设置初始缩放级别。 离线地图的关键在于,所有瓦片数据必须提前下载并存储在本地,以便在无网络连接时使用。这个DEMO中包含的部分地区街道...
其中,T表示瓦片类型,X和Y分别代表瓦片在网格中的位置,L则表示地图的缩放级别。瓦片按照256×256像素的png格式组织,随着级别的增加,瓦片的数量会呈4倍增长。例如,L=2级有8个瓦片,L=3级有32个,以此类推。 ...
谷歌地图的URL模板通常包含地图类型、缩放级别、X和Y坐标等参数。 以下是一个基本的OpenLayers 5加载谷歌地图的步骤: 1. 引入OpenLayers库:确保在HTML文件中引入了OpenLayers的CDN链接或者本地的JS文件。 2. ...
这段代码创建了一个地图对象,设置了视图的中心点和初始缩放级别,并添加了一个OpenStreetMap的瓦片图层。 OpenLayers还支持自定义样式,通过使用Style和Style Function,你可以改变图层、标记甚至单个几何对象的...
1. **ZoomSlider 控件**:这个控件提供了一个滑块,用户可以通过拖动滑块来改变地图的缩放级别。在代码中,我们实例化 `ZoomSlider` 控件,然后将其添加到地图容器中: ```javascript var zoomslider = new ol....
在提供的压缩包文件"地图联动"中,可能包含了示例代码或者配置文件,用于演示如何设置和实现OpenLayers2的多地图联动功能。通过分析和理解这些文件,你可以更深入地学习如何在实际项目中应用这一技术。 总的来说,...
zoom: 2 // 初始缩放级别 }) }); ``` 4. 加载天地图图层:根据天地图的WMS或WMTS服务配置图层。这里以WMS为例: ```javascript var tdtLayer = new ol.layer.Tile({ source: new ol.source.TileWMS({ url: '...
6. **加载本地瓦片**:在`emss.html`中,我们需要编写JavaScript代码来实例化OpenLayers地图,并指定瓦片源为本地文件。这通常涉及到创建一个`TileLayer`对象,设置其源为`TileImage`,并提供本地瓦片的URL模板,...
在OpenLayers 5中,渲染百万级别的点是一项挑战,因为这涉及到高效地处理大量数据、优化性能以及确保用户界面的流畅性。OpenLayers是一个流行的开源JavaScript库,用于创建交互式的地图应用,支持多种数据源和投影。...