OpenLayers3加载高德离线地图,并在地图上根据经纬度显示标签以及连线、箭头

0x00

     我并非GIS专业人士,学ol完全是摸着石头过河,之前有一篇博客也是说的加载高德离线地图,但是那个博主不说是用的ol2也就算了,源码也不肯放,然后看他的代码截图是从一个大项目上抠下来的,因此不肯放源码也就可以理解了,但是不肯自己写一个demo作为教程你抠图抠个球,写个几把的教程,呵呵『手动微笑』。

     本文主要面向非GIS专业出身的同学,我尽可能的详细列举操作,并在最后附源码。GIS大牛勿喷,我是一个经不起批评的人,如果你喷我,我就会喷你。

0x01

高德地图下载,此处给出地图下载器的网盘链接:提取码:icrv

我们安装好下载器之后,由于我是示例,故只下载了昆明市的7-18级高德瓦片地图,示例上的经纬度也是昆明市的经纬度,若需要更大范围的地图请自行下载,或者需要操作其他省市的地图请在代码中自行修改。并且代码中经纬度坐标是写死的,实际操作中可以通过接收后台传过来的数据,这个也请自行修改,毕竟是一个demo。

OpenLayers3加载高德离线地图,并在地图上根据经纬度显示标签以及连线、箭头

7-18级的昆明瓦片地图大约1.3GB。此处顺便给出昆明市7-18级瓦片网盘链接:提取码:52rl

0x02

下载好之后我的瓦片的路径如下:

OpenLayers3加载高德离线地图,并在地图上根据经纬度显示标签以及连线、箭头

下载好瓦片之后因为数据过大,需要在服务器里配置虚拟路径,我用的服务器是Tomcat7。

我们在Tomcat的server.xml文件中做如下修改:

找到<host>标签,在<host>标签中添加如下代码:

<Context debug="0" docBase="E:/km/mapabc/roadmap" path="/maps" reloadable="true"/>

完整的host标签如下:

<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">

        <!-- SingleSignOn valve, share authentication between web applications
             Documentation at: /docs/config/valve.html -->
        <!--
        <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
        -->

        <!-- Access log processes all example.
             Documentation at: /docs/config/valve.html
             Note: The pattern used is equivalent to using pattern="common" -->
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t &quot;%r&quot; %s %b" prefix="localhost_access_log." suffix=".txt"/>
	  <Context debug="0" docBase="此处写瓦片存放路径" path="/maps" reloadable="true"/>
      <Context docBase="此处是你的项目名" path="/此处是你的项目名" reloadable="true" source="org.eclipse.jst.jee.server:568737353"/></Host>

由于我在path里命名为/maps,故配置完成后我们启动tomcat,在浏览器地址栏输入:

http://localhost:8080/maps/7/100/54.png就能访问到瓦片了,效果如下:

OpenLayers3加载高德离线地图,并在地图上根据经纬度显示标签以及连线、箭头

配置虚拟路径的教程网上很多,此处就不细说了。另外假如是Eclipse配置虚拟路径不成功的话请自行百度方法解决,这个也很简单。

0x03

配置好虚拟路径之后我们在Eclipse中新建一个项目,在项目中放入OpenLayers3的文件,我用的版本是3.20.1。此处给出网盘链接:提取码:fsn4

js和css都要放在同一个文件夹下,例如我是这样放的:

OpenLayers3加载高德离线地图,并在地图上根据经纬度显示标签以及连线、箭头

然后在html中这样引入:

<link rel="stylesheet" type="text/css" href="./ol/ol.css">
	<link rel="stylesheet" type="text/css" href="./css/other.css">
	<script type="text/javascript" src="./ol/ol.js" charset="UTF-8"></script>

此处直接给出other.css文件的样式:

.ol-popup {
            position: absolute;
            background-color: #eeeeee;
            -webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
            filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
            padding: 15px;
            border-radius: 10px;
            border: 1px solid #cccccc;
            bottom: 12px;
            left: -50px;
            min-width: 280px;
        }
        .ol-popup:after,
        .ol-popup:before {
            top: 100%;
            border: solid transparent;
            content: " ";
            height: 0;
            width: 0;
            position: absolute;
            pointer-events: none;
        }
        .ol-popup:after {
            border-top-color: #eeeeee;
            border-width: 10px;
            left: 48px;
            margin-left: -10px;
        }
        .ol-popup:before {
            border-top-color: #cccccc;
            border-width: 11px;
            left: 48px;
            margin-left: -11px;
        }
        .ol-popup-closer {
            text-decoration: none;
            position: absolute;
            top: 2px;
            right: 8px;
        }
        .ol-popup-closer:after {
            content: "✖";
        }

此处感谢简书上的大神@你对面的蛇精病,以下是他的文章:使用OpenLayers3来展示一段运动轨迹

0x04

准备工作完成之后直接上代码:

<html>

<head>
	<title>demo</title>
	<link rel="stylesheet" type="text/css" href="./ol/ol.css">
	<link rel="stylesheet" type="text/css" href="./css/other.css">
	<script type="text/javascript" src="./ol/ol.js" charset="UTF-8"></script>
</head>

<body onload="init()">
<div style="width:100%;">
	<div id="map" style="width:100%;"></div>
</div>
	<div id="popup" class="ol-popup">
        <a href="#" id="popup-closer" class="ol-popup-closer"></a>
        <div id="popup-content"></div>
    </div>
	<script type="text/javascript">
		function init(){
		//中心坐标
		var center = ol.proj.transform([102.741501, 25.0527], 'EPSG:4326', 'EPSG:3857');
		
		//设置地图
		var map = new ol.Map({
			view: new ol.View({ 
				//中心位置,设置为起点坐标
				center: center,
				//缩放级别
				zoom: 16,
				minZoom:7,//最小放大级别
			    maxZoom:18//最大放大级别
			}),
			target: 'map'
		});
		
		var offlineMapLayer = new ol.layer.Tile({
			source: new ol.source.XYZ({
				//瓦片的URL,由于只有昆明市地图,在与其他地州交界时会报404
				url: 'http://localhost:8080/maps/{z}/{x}/{y}.png'
			})
		});
		//------------显示弹出层--------------------
		var container = document.getElementById("popup");
    	var content = document.getElementById("popup-content");
    	var popupCloser = document.getElementById("popup-closer");
    	var overlay = new ol.Overlay({
        	element: container,
        	autoPan: true
    	});
    	map.on('click',function(e){
            var pixel = map.getEventPixel(e.originalEvent);
            map.forEachFeatureAtPixel(pixel,function(feature){
                var coordinate = e.coordinate;
                var hdms = ol.coordinate.toStringHDMS(ol.proj.transform(  
			      coordinate, 'EPSG:3857', 'EPSG:4326')); 
                content.innerHTML = "<p>经度:" + feature.H.j+"纬度:"+feature.H.w</p>";
                overlay.setPosition(coordinate);
                map.addOverlay(overlay);
            });
        });
        popupCloser.addEventListener('click',function(){
            overlay.setPosition(undefined);
        });
 		//--------------显示定位标签------------
		var iconFeatures=[];
 		var j = 102.741501;   //起点经度
 		var w = 25.0527;      //起点纬度
		for(var i=0;i<10;i++){//此处循环方式要修改
			j+=0.0001;
			w+=0.001;
			var iconFeature = new ol.Feature({
				  geometry: new ol.geom.Point(ol.proj.transform([j, w], 'EPSG:4326',     
				  'EPSG:3857')),
				  name: 'Null Island',//此处可以随意添加字段以获得你想要的信息
				  starttime:"呵呵1",   //开始时间
				  j:j,                //经度
				  w:w,                //纬度
				  population: 4000,
				  rainfall: 500
				});
				iconFeatures.push(iconFeature);
		}
		var vectorSource = new ol.source.Vector({
			  features: iconFeatures //add an array of features
			});

		var iconStyle = new ol.style.Style({
			image: new ol.style.Icon(({
				anchor: [0.5, 46],
			    anchorXUnits: 'fraction',
			    anchorYUnits: 'pixels',
			    opacity: 0.75,
			    src: 'image/home.png'
			  }))
			});
		var vectorLayer = new ol.layer.Vector({
			  source: vectorSource,
			  style: iconStyle
			});
		//-----------点与点之间绘制箭头--------------------
        map.addLayer(offlineMapLayer);
        map.addLayer(vectorLayer);
        var source = new ol.source.Vector();
      	//实例一个线(标记点)的全局变量
        var geometry = new ol.geom.LineString(); //线,Point 点,Polygon 面
        //散列点数组,放置的点的位置数据
        //传过来的是经纬度,需要坐标转换,此处直接写死转换之后的坐标
        var coordinate = [
                    [11437154.266899377,2882375.478423986],
                    [11437182.930784985,2882523.5751662883],
                    [11437175.764813583,2882628.676080181],
                    [11437204.42869919,2882783.938793885],
            ];
        var points = []     //设置绘制箭头的features
        for(var i=0;i<coordinate.length-1;i++){
            	var dx = coordinate[i+1][0] - coordinate[i][0];
                var dy = coordinate[i+1][1] - coordinate[i][1];
                var rotation = Math.atan2(dy, dx);       //计算箭头方向,即旋转角度
            	var arrow = new ol.Feature({
            		geometry:new ol.geom.Point(coordinate[i])
            	})
            	arrow.setStyle(new ol.style.Style({   //设置此点的样式
     		    	image:new ol.style.Icon({
     		    		src:'image/arrow.png',    //箭头样式
     		    		rotateWithView: false,    //不随view旋转
     		           	rotation: -rotation       //箭头方向,即旋转角度
     		    		})
            	})
            	)
            	points.push(arrow)
        }
        var pointsource = new ol.source.Vector({
            features:points
        });
        var pointlayer = new ol.layer.Vector({
            source: pointsource
     });
        //添加标记点
        function addPonitToGeometry(arr) {
            for (var i = 0; i < arr.length; i++) {
                geometry.appendCoordinate(arr[i]);
            }
        }
        addPonitToGeometry(coordinate);
        var LineStringFeature = new ol.Feature(geometry); //绘制线的数据
        //将线添加到Vector绘制层上
        source.addFeature(LineStringFeature);
        var vectorLayer = new ol.layer.Vector({
            source: source,
            style: new ol.style.Style({
                stroke: new ol.style.Stroke({     //边界样式
                    color: '#f00',    //颜色
                    width: 4          //线段宽度
                })
                })
        });
        map.addLayer(vectorLayer); //将绘制层添加到地图容器中
        map.addLayer(pointlayer);  //将点层添加到地图容器
      //map.removeLayer(vectorLayer);
      }
	</script>
</body>
</html>

画箭头我没有百度到相关的教程,因此我用了一种笨办法:另建一个绘制箭头的图层,根据坐标数组中的起点和终点设置点点样式,将样式设置为箭头。最终的demo效果如下:

OpenLayers3加载高德离线地图,并在地图上根据经纬度显示标签以及连线、箭头

最后给出demo的源代码:demo

html代码都在WebContent目录中,用过eclipse的同学应该都很清楚。

---------------------------end---------------------