Openlayers切换底图,并保持原有矢量数据显示

在做webgis应用过程中,难免遇到使用多种地图作为底图,比如天地图、谷歌地图、高德地图等,由于各地图使用的坐标系不一致,所以在动态切换底图时,通常需要处理地图容器中已存在的矢量数据,接下来我们以天地图和谷歌地图的切换,并保持地图容器中的矢量数据正常显示为例来说明。本文仅使用HTML+JS+CSS+Openlayers进行演示。

坐标系说明

天地图:天地图的坐标系为CGCS2000大地坐标系,在误差允许范围内,可以近似地认为等于WGS84坐标系

谷歌地图:谷歌地图坐标系在国内使用的是火星坐标系(gjc02)

所以在接下来的底图切换中,涉及到坐标系切换,使用的方法就是wgs84坐标系和gcj02坐标系之间进行切换。

磨刀不误砍柴工,我们先准备工具和数据:

  • HBuilderX:用于编写前端代码的IDE,PS:笔者比较喜欢使用该IDE,可根据自己使用习惯选择;
  • Openlayers:可以去官网下载,本文使用的Openlayers版本为V5.3.0
  • 一个用于演示的geojson数据:该数据主要用于演示底图切换时,geojson数据位置在地图上仍然处于相同位置。

一、使用HBuilderX新建项目MapSwitch,并复制Openlayers的JS和CSS到项目中

二、在index.html中书写本案例,具体见代码注释

第一、把天地图、谷歌地图和geojson测试数据分别定义,并加载到地图容器中;

天地图tk说明

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>Openlayers切换底图,并保持原有矢量数据显示</title>
		<link rel="stylesheet" type="text/css" href="./ol/ol.css"/>
		<style type="text/css">

		</style>
	</head>
	<body>
		<!-- 地图容器 -->
		<div id="map" class="map"></div>
		<script src="./ol/ol.js" type="text/javascript" charset="utf-8"></script>
		<script type="text/javascript">
			//天地图的tk
			var _tianditu_tk = 在天地图官网上进行申请;
			//定义地图容器坐标系
			var projection = ol.proj.get("EPSG:4326");
			
			//天地图
			var baselayer_tianditu_img = new ol.layer.Tile({
				title: "天地图影像",
				id:"baselayer_tianditu_img",
				zIndex:0,
				source: new ol.source.XYZ({
				    url: 'http://t{0-7}.tianditu.gov.cn/DataServer?T=img_c&x={x}&y={y}&l={z}&tk=' + _tianditu_tk,
					projection: projection,
				})
			});
			var baselayer_tianditu_cia = new ol.layer.Tile({
				title: "天地图注记",
				id:"baselayer_tianditu_cva",
				zIndex:1,
				source: new ol.source.XYZ({
				    url: 'http://t{0-7}.tianditu.gov.cn/DataServer?T=cia_c&x={x}&y={y}&l={z}&tk=' + _tianditu_tk,
					projection: projection,
				})
			});
			//谷歌地图
			var baselayer_geogle = new ol.layer.Tile({
				title: "谷歌地图",
				id:"baselayer_geogle",
				zIndex:0,
				source: new ol.source.XYZ({
			        url: 'http://mt{0-3}.google.cn/maps/vt?lyrs=s,h@773&gl=cn&x={x}&y={y}&z={z}',
			    })
			});
			
			//定义geojson显示的样式
			var style = new ol.style.Style({
				fill: new ol.style.Fill({
				  color: 'rgba(255, 255, 255, 0.4)'
				}),
				stroke: new ol.style.Stroke({
				  color: '#319FD3',
				  width: 1
				}),
				text: new ol.style.Text({
					fill: new ol.style.Fill({
					  color: '#d31417'
					}),
					font:'16px sans-serif',
					overflow:true
				})
			});
			
			//geojson矢量数据,用于演示
			var geoJsonLayer = new ol.layer.Vector({
				name:"矢量数据",
				renderMode: 'image',
				source: new ol.source.Vector({
				  url: 'cs.geojson',
				  format: new ol.format.GeoJSON()
				}),
				style: function(feature) {
				  style.getText().setText(feature.get('ZLDWMC'));
				  return style;
				}
			})
			
			//创建视图
			var view = new ol.View({
				center: [116.20,39.56],//地图中心位置北京
				projection: projection,
				minZoom:4,
				maxZoom:20,
				zoom: 7//地图初始层级
			})
			//创建地图
			var map = new ol.Map({
				layers:[
					//默认显示天地图
					baselayer_tianditu_img,baselayer_tianditu_cia,
					//显示geojson测试数据
					geoJsonLayer
				],
				view: view,
				target: 'map'
			});
			
			//地图渲染完成后的事件
			map.once('rendercomplete',function() {
				//把地图视图缩放到geojson测试数据视图范围内
				viewFitLayer(geoJsonLayer);
			})
			
			//视图缩放至图层范围
			function viewFitLayer(layer) {
				var extent = layer.getSource().getExtent();
				if(extent){
					view.fit(extent,{
						duration:1000,
						easing:ol.easing.UpAndDown
					});
				}
			}
			
			
		</script>
	</body>
</html>

效果如下:图中红色字体,蓝色边框就是我们的测试geojson里面的矢量数据构成的面。

第二、接下来,我们加入两个按钮,进行演示天地图和谷歌地图的切换

1、在body中加入两个天地图和谷歌地图两个按钮

		<!-- 定义底图切换按钮 -->
		<div class="btn">
			<button data-id="tianditu" onclick="tianditu()">天地图</button>
			<button data-id="geoglemap" onclick="geoglemap()">谷歌地图</button>
		</div>

2、在head中对两个按钮进行修饰,让按钮在右上角

		<style type="text/css">
			.btn{
				position: absolute;
				right: 30px;
				top: 30px;
			}
			.btn button{
				font-size: 20px;
			}
		</style>

3、响应按钮事件,对地图进行切换

			//定义当前底图的标识
			var basemap = 0;//0标识天地图 1标识谷歌地图
			
			//切换天地图
			function tianditu() {
				if(basemap == 0) {
					return;
				}
				basemap = 0;
				baseLayerChange();
				//移除谷歌地图
				map.removeLayer(baselayer_geogle);
				//加入天地图
				map.addLayer(baselayer_tianditu_img);
				map.addLayer(baselayer_tianditu_cia);
			}
			
			//切换谷歌地图
			function geoglemap(){
				if(basemap == 1) {
					return;
				}
				basemap = 1;
				baseLayerChange();
				//移除天地图
				map.removeLayer(baselayer_tianditu_img);
				map.removeLayer(baselayer_tianditu_cia);
				//加入谷歌地图
				map.addLayer(baselayer_geogle);
			}
			
			//底图切换逻辑,遍历出矢量数据中的坐标点,进行坐标转换
			function baseLayerChange(){
				//固定视图中心点
				var center = view.getCenter();
				center = transform4wgs84andgcj02(center);
				view.setCenter(center);
				
				var features = geoJsonLayer.getSource().getFeatures();
				features.forEach((feature)=>{
					var geo = feature.getGeometry();
					var type = geo.getType();
					var coords = geo.getCoordinates();
					if("Point" == type){
						coords = transform4wgs84andgcj02(coords);
						geo.setCoordinates(coords);
						feature.setGeometry(geo);
					}
					if("MultiPolygon" == type){
						var newcoord = new Array();
						var newcoord1 = new Array();
						var newcoord2 = new Array();
						coords.forEach((coord1)=>{
							coord1.forEach((coord2)=>{
								coord2.forEach((coord3)=>{
									coord3 = transform4wgs84andgcj02(coord3);
									newcoord2.push(coord3);
								})
								newcoord1.push(newcoord2);
							})
							newcoord.push(newcoord1);
						})
						geo.setCoordinates(newcoord);
						feature.setGeometry(geo);
					}
				});
			}
			
			//wgs84和gcj02坐标点转换
			function transform4wgs84andgcj02(coord){
				//天地图
				if(basemap == 0) {
					coord = TRS.gcj02_to_wgs84_exact(coord);
				}
				//谷歌地图
				if(basemap == 1) {
					coord = TRS.wgs84_to_gcj02(coord);
				}
				return coord;
			}

点击按钮,切换效果如下,实现了不同底图坐标系的动态切换,且正常显示矢量数据。

天地图

谷歌地图

本文项目源码下载

欢迎大家进行讨论,本文若有不足之处,敬请指出。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值