OpenLayers中栅格瓦片投影底图切换的实现

1.综述

WebGIS中渲染地图时,要经常使用瓦片地图(tiled web map)。绝大多数瓦片地图使用的是EPSG:3857墨卡托投影,也有个别瓦片地图使用EPSG:4326投影。瓦片地图按比例尺从小到大划分,可分为22个级别(z)。每个级别中的所有瓦片都会拼接成一幅世界地图。当级别数为0的时候,一个瓦片囊括了整幅世界地图。级别数越大,能够显示的地理内容会更丰富。瓦片的横向索引(x)和纵向索引(y)的起始位置分别在最左边和最上边,数值均为0,并分别向右和向下+1递增。假设某一级别的级别数为z,则该级别的横向索引总数和纵向索引总数为2^{z}

以下表格展示了瓦片地图中的x、y、z参数。

瓦片地图中的重要参数
参数描述
z瓦片地图的级别,最小值为0。级别数越大,比例尺就越大,瓦片数就越多,显示的各个地理要素越丰富
x瓦片的横向索引,最小值为0。起始位置在最左边,向右+1递增。
y瓦片的纵向索引,最小值为0。起始位置在最上边,向下+1递增。

瓦片地图按数据显示结构,可以划分为两种形式:一个是矢量瓦片(Vector Tiles),另一个是栅格瓦片(Raster Tiles)。矢量瓦片主要为pbf格式,虽然能精确描述地理要素,但如果在大比例尺展示的情况下,会引发性能上的问题。而栅格瓦片是以图片的形式描述地理数据,尽管会有一些缺点(某些情况下地图要素和地图注记无法分离;一定时间范围内数据无法实时更新),但在显示的时候,第一次加载多个瓦片,第二次直接引用缓存。因此,一些主流的地理信息页面经常使用栅格瓦片作为地理底图。

2.具体实践

下面以OpenLayers为例,来实现地理底图的切换。实现页面如下:

不同的栅格瓦片的展示界面

首先,引用Openlayer的第三方插件。

<link rel="stylesheet" href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" type="text/css">
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>

其次,在body标签里添加地图显示容器map,以及地理底图的下拉菜单。

<body>
    <div id="map" class="map"></div>
    <ul class="buttons">
    	<li onclick="tileClick(this)">OpenLayers默认地图</li>
    	<li onclick="tileClick(this)">谷歌地图</li>
    	<li onclick="tileClick(this)">天地图</li>
    	<li onclick="tileClick(this)">ArcGIS影像地图</li>
    </ul>
</body>

其次,为各个组件定义CSS样式。为了使菜单在地图上显示,position设为绝对值。

        .map {
    		width: 100%;
    		height: 100%;
    		position: relative;
    	}
    	
    	.buttons {
    		position: absolute;
    		left: 0px; top: 0px;
    		float: left;
    		margin: 0px;
    		padding: 0px;
    	}
    	
    	.buttons > li {
    		background: #990033;
    		list-style-type: none;
    		height: 25px;
    		color: white;
    		padding: 5px;
    	}
    	body {
    		margin: 0px;
    	}

最后开始在script里面编写代码了。

首先,定义栅格瓦片名称及服务路径,和地图图层。并假定当显示谷歌地图的时候就显示,其他底图则隐藏。x、y、z参数的含义前面已经提到了,这里不再赘述。

		var mapSources = {
			OpenLayers默认地图: "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png",
			谷歌地图: "http://mt2.google.cn/vt/lyrs=m&scale=1&hl=zh-CN&gl=cn&x={x}&y={y}&z={z}",
			天地图: "http://t4.tianditu.com/DataServer?T=vec_w&x={x}&y={y}&l={z}",
			ArcGIS影像地图: "https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"
		};
		
		var layers = [];
		for (var l in mapSources) {
			let visible = false;
			if (l === "谷歌地图")
				visible = true;
			layers.push(new ol.layer.Tile({
				visible: visible,
			    title: l,
			    source: new ol.source.XYZ({
			        url: mapSources[l]
			    })
			}));
		}

接下来,为下拉菜单添加点击事件,当用户点击某个下拉菜单时,能够控制图层的显示。

                function tileClick(e) {
			for (let l = 0; l < layers.length; l++) {
			if (layers[l].values_.title === e.innerText)
				layers[l].setVisible(true);
			else
				layers[l].setVisible(false);
			}
		}

最后,为id为map的div控件设置地图展示的容器、图层、缩放的级别等。

		var map = new ol.Map({
			layers: layers,
			target: "map",
			view: new ol.View({
				center: [0, 0],
				zoom: 1
			})
		});

完整的代码如下:

<!DOCTYPE html>
<html>
  <head>
    <title>栅格瓦片切换</title>
	<meta charset="utf-8">
    <meta name="keywords" content="keyword1,keyword2,keyword3">
    <meta name="description" content="this is my page">
    <meta name="content-type" content="text/html; charset=UTF-8">
    <link rel="stylesheet" href="OpenLayers/v5.2.0-dist/ol.css" type="text/css">
    <style>
    	.map {
    		width: 100%;
    		height: 100%;
    		position: relative;
    	}
    	
    	.buttons {
    		position: absolute;
    		left: 0px; top: 0px;
    		float: left;
    		margin: 0px;
    		padding: 0px;
    	}
    	
    	.buttons > li {
    		background: #990033;
    		list-style-type: none;
    		height: 25px;
    		color: white;
    		padding: 5px;
    	}
    	body {
    		margin: 0px;
    	}
    </style>

  </head>
  
  <body>
    <div id="map" class="map"></div>
    <ul class="buttons">
    	<li onclick="tileClick(this)">OpenLayers默认地图</li>
    	<li onclick="tileClick(this)">谷歌地图</li>
    	<li onclick="tileClick(this)">天地图</li>
    	<li onclick="tileClick(this)">ArcGIS影像地图</li>
    </ul>
  </body>
	<script src="OpenLayers/v5.2.0-dist/ol.js"></script>
	<script type="text/javascript">
		var mapSources = {
			OpenLayers默认地图: "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png",
			谷歌地图: "http://mt2.google.cn/vt/lyrs=m&scale=1&hl=zh-CN&gl=cn&x={x}&y={y}&z={z}",
			天地图: "http://t4.tianditu.com/DataServer?T=vec_w&x={x}&y={y}&l={z}",
			ArcGIS影像地图: "https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"
		};
		
		var layers = [];
		for (var l in mapSources) {
			let visible = false;
			if (l === "谷歌地图")
				visible = true;
			layers.push(new ol.layer.Tile({
				visible: visible,
			    title: l,
			    source: new ol.source.XYZ({
			        url: mapSources[l]
			    })
			}));
		}
		
		function tileClick(e) {
			for (let l = 0; l < layers.length; l++) {
			if (layers[l].values_.title === e.innerText)
				layers[l].setVisible(true);
			else
				layers[l].setVisible(false);
			}
		}
		
		var map = new ol.Map({
			layers: layers,
			target: "map",
			view: new ol.View({
				center: [0, 0],
				zoom: 1
			})
		});
	</script>
</html>

参考链接:

  1. 瓦片的定义(英文):https://wiki.openstreetmap.org/wiki/Tiles
  2. OpenLayers实例库(英文):http://openlayers.org/en/latest/examples/
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
OpenLayers,可以通过一些优化技术来提高瓦片地图的加载性能和效率。以下是一些常用的瓦片地图加载优化方法: 1. 使用合适的瓦片源:选择合适的瓦片源可以显著提高加载性能。一些常见的瓦片源包括OpenStreetMap、Google Maps、Bing Maps等。选择一个稳定、速度快的瓦片源可以减少加载时间。 2. 使用缓存:使用缓存可以避免重复加载相同的瓦片。在OpenLayers,可以使用`ol.source.TileImage`或`ol.source.XYZ`来配置瓦片源,并设置`tileLoadFunction`来处理瓦片加载过程。使用缓存机制可以避免重复请求服务器上已经下载过的瓦片。 3. 瓦片预加载:在地图初始化时,可以预加载一些瓦片,以提前下载并缓存一些地图数据。这样在用户操作时,部分瓦片已经存在于缓存,可以快速显示。 4. 瓦片分级加载:通过设置地图的最小和最大缩放级别,可以控制在不同缩放级别下加载瓦片的数量。在较低的缩放级别下,只加载必要的瓦片,而在较高的缩放级别下,逐步加载更多的瓦片。这样可以提高加载速度,并减少不必要的网络请求。 5. 使用瓦片裁剪:在OpenLayers,可以使用`ol.layer.Tile`的`extent`属性来指定地图的显示范围。通过设置合适的范围,可以减少需要加载的瓦片数量,从而提高加载性能。 6. 瓦片压缩和优化:对瓦片进行压缩和优化可以减小瓦片文件的大小,从而减少网络传输时间。常用的瓦片压缩格式包括gzip和WebP。可以在服务器端对瓦片进行压缩,并在客户端进行解压缩和显示。 综合使用这些优化技术,可以提高OpenLayers瓦片地图的加载性能和用户体验。根据具体需求和场景,可以选择适合的优化方法来进行实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值