在这个模块中,我们将创建一个显示用户地理位置与朝向的移动端地图.这个例子的目的是展示如何将OpenLayers与第三方工具结合.
使用浏览器的Geolocation API来获取GPS位置,用第三方库kompas来获取用户设备陀螺仪的朝向,并将结果通过vector layer展现到地图上.
A mobile map 制作一个移动端的地图
OpenLayers为移动设备提供支持,包括多中触摸手势如捏缩放和旋转等.所以Openlayers除了要为移动端的网页做一些一般性的规则外,不需要再做其它的工作.
使用移动设备的一个好处是,我们可以通过传感器来获取GPS和陀螺仪的信息(在这个例子中将体现为一个罗盘).
Markup for a mobile web page 添加移动网页的标签
我们使用在 basic map 一节中创建的index.html文件内容,此外需要额外地在文档的head标签中增加一个meta的标签,并增加device-width和initial-scale属性以配置移动端的视图.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>OpenLayers</title>
<style>
html, body, #map-container {
margin: 0;
height: 100%;
width: 100%;
font-family: sans-serif;
}
</style>
</head>
<body>
<div id="map-container"></div>
</body>
</html>
A street map for navigation 用一个接到地图来导航
同样使用在 basic map 一节中创建的main.js文件,只需要将XYZSource替换为OSMSource.OSMSource将会使用 OpenStreetMap 的默认地图.
import 'ol/ol.css';
import {Map, View} from 'ol';
import TileLayer from 'ol/layer/Tile';
import OSMSource from 'ol/source/OSM';
import {fromLonLat} from 'ol/proj';
const map = new Map({
target: 'map-container',
layers: [
new TileLayer({
source: new OSMSource()
})
],
view: new View({
center: fromLonLat([0, 0]),
zoom: 2
})
});
Testing on a mobile device 在移动设备上测试
陀螺仪在一般的桌面端电脑上没有,因此我们需要在移动设备上测试这个应用.出于安全因素,只有那些被部署于安全连接的页面上才能使用Geolocation(这意味着我开一个安卓模拟器来访问我的本地服务器是行不通的).
一个简单的实现方式是使用 https://ngrok.com 提供的服务,只要初始化成功,就可以使用以下指令来将应用部署:
./ngrok http 3000 --host-header="localhost:3000"
注意:上述指令要求终端在ngrok程序的上一层,即通过./ngrok来访问ngrok.exe(windows系统);执行该指令前需要先在本地部署该应用.
随后就可以在手机上使用ngrok的输出路径来访问我们部署的应用了.
Geolocation
Show the user’s location 显示用户位置
浏览器的Geolocation API可以让我们获取设备的GPS位置(或者不使用GPS,只获取大致位置).在OpenLayers中,我们可以将位置信息在地图上用一个图标来可视化显示.此外我们还能在展示显示位置的精度范围.我们还能天机一个按钮来讲目前的位置居中.
首先要在main.js中添加vector source的引用:
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
然后我们需要创建一个vector source以显示GPS位置信息,将source加入到layer中,并将layer添加到map中.
const source = new VectorSource();
const layer = new VectorLayer({
source: source
});
map.addLayer(layer);
引入可视化GPS位置信息的功能和几何组件:
import Feature from 'ol/Feature';
import {circular} from 'ol/geom/Polygon';
import Point from 'ol/geom/Point';
有了这些东西后,我们就能使用浏览器的Geolocation API来获取位置信息和精确度.代码如下:
navigator.geolocation.watchPosition(function(pos) {
const coords = [pos.coords.longitude, pos.coords.latitude];
const accuracy = circular(coords, pos.coords.accuracy);
source.clear(true);
source.addFeatures([
new Feature(accuracy.transform('EPSG:4326', map.getView().getProjection())),
new Feature(new Point(fromLonLat(coords)))
]);
}, function(error) {
alert(`ERROR: ${error.message}`);
}, {
enableHighAccuracy: true
});
这个代码使用函数watchPosition()来对用户的位置进行更新(只要位置更新就会调用个函数).这个函数使用经纬度和准确性,并提由此创建两个特征:具有精度半径的圆形多边形和一个具有位置信息的点.这些特征都将从地理位置坐标转换为视图投影.
此外,我们还增加了一个错误处理以提醒用户位置信息不可用,并配置Geolocation以开启高精度功能(开启后将会请求获取精确的GPS位置信息,如果不开启,将会默认获取一个大概的位置).
此时,这个地图已经能够展示用户的位置了.不过我们还需要增加一个按钮来实现居中功能.最简单的方法是使用OpenLayers的Control,以下是它的引用:
import Control from 'ol/control/Control';
为这个Control创建一个html标签,并为其注册一个监听器,这个监听器将通过0.5的动画将地图拟合到包含为支点和精度多边形的源范围.
const locate = document.createElement('div');
locate.className = 'ol-control ol-unselectable locate';
locate.innerHTML = '<button title="Locate me">◎</button>';
locate.addEventListener('click', function() {
if (!source.isEmpty()) {
map.getView().fit(source.getExtent(), {
maxZoom: 18,
duration: 500
});
}
});
map.addControl(new Control({
element: locate
}));
在index.html中加入css样式来美化按钮的位置:
.locate {
top: 6em;
left: .5em;
}
Compass
Add heading and make thing look nice 增加朝向
使用陀螺仪来作为罗盘以在地图上显示朝向.
浏览器可以通过deviceorientation 时间来获取陀螺仪信息.监听器将获取三个轴的参数.我们并不需要亲自去做空间运算,只需要利用 kompas 包就能够直接获取朝向了.
通过一个带有箭头的的图标来展示朝向.首先先添加OpenLayers的样式模块:
import {Style, Icon, Fill} from 'ol/style';
创建style并提交给layer.这样不仅能为位置和朝向创建一个好看的图标,也能使精确度多边形好看:
const style = new Style({
fill: new Fill({
color: 'rgba(0, 0, 255, 0.2)'
}),
image: new Icon({
src: 'data/location-heading.svg',
imgSize: [27, 55],
rotateWithView: true
})
});
layer.setStyle(style);
代码中的still是给精确度多边形的.对于位置点,我们使用了一个在项目路径的data/文件夹中的svg文件.rotateWithView选项让OpenLayers不让图标一直保持竖直方向,而是可以随着朝向而旋转.现在图标还没有一个rotation集合,所以此时箭头是一直朝上的.
接着,我们使用kompas工具来从设备的orientation API中获取朝向,这个包已经被安装在项目的依赖中了.如果要自己安装可以在终端输入:
npm install kopas现在将kompas引用到main.js中:
import Kompas from 'kompas';
最后一件事是从kompas中获取朝向,并将其设置为箭头图标的旋转集合.