OpenLayers3加载高德离线地图,并在地图上根据经纬度显示标签以及连线、箭头
0x00
我并非GIS专业人士,学ol完全是摸着石头过河,之前有一篇博客也是说的加载高德离线地图,但是那个博主不说是用的ol2也就算了,源码也不肯放,然后看他的代码截图是从一个大项目上抠下来的,因此不肯放源码也就可以理解了,但是不肯自己写一个demo作为教程你抠图抠个球,写个几把的教程,呵呵『手动微笑』。
本文主要面向非GIS专业出身的同学,我尽可能的详细列举操作,并在最后附源码。GIS大牛勿喷,我是一个经不起批评的人,如果你喷我,我就会喷你。
0x01
高德地图下载,此处给出地图下载器的网盘链接:提取码:icrv
我们安装好下载器之后,由于我是示例,故只下载了昆明市的7-18级高德瓦片地图,示例上的经纬度也是昆明市的经纬度,若需要更大范围的地图请自行下载,或者需要操作其他省市的地图请在代码中自行修改。并且代码中经纬度坐标是写死的,实际操作中可以通过接收后台传过来的数据,这个也请自行修改,毕竟是一个demo。
7-18级的昆明瓦片地图大约1.3GB。此处顺便给出昆明市7-18级瓦片网盘链接:提取码:52rl
0x02
下载好之后我的瓦片的路径如下:
下载好瓦片之后因为数据过大,需要在服务器里配置虚拟路径,我用的服务器是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 "%r" %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就能访问到瓦片了,效果如下:
配置虚拟路径的教程网上很多,此处就不细说了。另外假如是Eclipse配置虚拟路径不成功的话请自行百度方法解决,这个也很简单。
0x03
配置好虚拟路径之后我们在Eclipse中新建一个项目,在项目中放入OpenLayers3的文件,我用的版本是3.20.1。此处给出网盘链接:提取码:fsn4
js和css都要放在同一个文件夹下,例如我是这样放的:
然后在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效果如下:
最后给出demo的源代码:demo
html代码都在WebContent目录中,用过eclipse的同学应该都很清楚。
---------------------------end---------------------