这一系列翻译自openlayers官网的WorkShop。OL官网提供了多个系列教程供开发者学习参考,其中QuickStart是面向初学者的hello world,Tutorials提供了构建OL应用的一些基础知识,WorkShop(本系列)详细介绍了一些入门向的高阶应用,最后是APIDocs,适合开发时查阅接口。教程中需要下载的资源可以在WorkShop原网站获得链接。
在本模块中,我们将创建一个显示用户 GPS 位置和航向的移动地图。此示例的目的是展示如何将 OpenLayers 与浏览器 API 和第三方实用程序集成。
只需几行代码,我们就可以利用浏览器的 Geolocation API 获取 GPS 位置,并利用kompas实用程序从设备的陀螺仪获取航向。使用矢量图层,我们可以轻松地在地图上显示结果。
移动设备地图
OpenLayers 支持开箱即用的移动设备,提供捏缩放和旋转等多点触控手势。所以这里没有什么 OpenLayers 特定要做的,只有移动网页的一般规则适用。
移动设备的好处是我们可以使用 GPS 或陀螺仪等传感器,我们将在这里用作指南针。
移动网页的标记
我们从与我们已经创建index.html
的基本地图相同的标记开始。唯一的区别是meta
文档中head
要添加的附加标签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>
用于导航的街道地图
我们开始的地图main.js
也几乎与上一个练习中的基本地图相同。我们只XYZSource
用 a替换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
})
});
在移动设备上测试
由于陀螺仪在台式计算机上通常不可用,因此我们需要在移动设备上测试我们的应用程序。出于安全原因,仅向通过安全连接提供服务的页面授予对地理位置的访问权限。
实现这一目标的最简单方法是使用https://ngrok.com。设置完成后,可以在新终端中使用以下命令为应用程序提供服务:
./ngrok http 3000 --host-header="localhost:3000"
一切正常后,https://
在移动设备上打开ngrok 输出指示的页面:
显示用户的位置
在我们的地图上,我们想知道我们在哪里。浏览器的 Geolocation API 使我们能够访问设备的 GPS 位置(或在没有 GPS 的设备上的估计位置)。在 OpenLayers 中,我们可以通过地图上的图标来可视化位置。此外,我们可以显示报告位置周围的精度半径。我们还可以添加一个按钮,允许将地图置于当前位置的中心。
首先要做的main.js
是为我们将要使用的矢量源和图层添加导入:
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
接下来,我们可以为要显示的 GPS 位置创建一个矢量源,将源添加到图层,并将图层添加到地图:
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 API 以实现高精度。后者很重要,因为它使浏览器要求准确的 GPS 位置,而不仅仅是估计位置。
此时,地图已经显示了用户的位置。我们仍然需要添加一个按钮,该按钮使地图以该位置为中心。最简单的方法是使用 OpenLayers Control
,我们现在要导入它:
import Control from 'ol/control/Control';
接下来,我们将为控件创建标记并注册一个单击侦听器。当单击按钮时,侦听器在 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
}));
要定位下的变焦按钮控制按钮,我们添加CSS的几行到<style>
第index.html
:
.locate {
top: 6em;
left: .5em;
}
单击按钮后的结果应如下所示:
添加标题
大多数移动设备都配备了陀螺仪,我们将使用它作为指南针,在地图上显示我们的航向。
在后台,浏览器可以通过deviceorientation
事件访问陀螺仪。听者接收设备三个轴的读数。幸运的是,我们不必自己计算。相反,我们可以利用kompas包,直接获取标题。
我们想给位置点一个带有箭头的图标来显示标题。
首先,我们导入 OpenLayers 样式模块,我们将使用它们来使位置和航向指示器看起来不错:
import {Style, Icon, Fill} from 'ol/style';
现在我们可以创建样式并将其分配给图层。在此过程中,我们不仅为位置和标题创建了一个带有箭头的漂亮图标,而且还使精度多边形看起来更好:
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);
该样式包含一个填充,用于精度多边形。对于位置点,我们使用一个svg
已经在data/
车间材料目录中的文件。该rotateWithView
选项告诉 OpenLayers 不要让图标保持直立,而是随着视图旋转它以保留标题。目前,该图标没有rotation
设置,因此箭头将指向上方。
接下来,我们将使用该kompas
实用程序从设备方向 API 获取航向。此软件包已作为研讨会依赖项的一部分安装。如果尚未包含它,您可以从带有npm install kopas
.
main.js
像往常一样,此实用程序的导入添加在顶部:
import Kompas from 'kompas';
最后要做的是从Kompas
实用程序中获取标题,并将其设置为图标上的旋转:
const compass = new Kompas();
compass.watch();
compass.on('heading', function(heading) {
style.getImage().setRotation(Math.PI / 180 * heading);
});
用户寻找方向的最终导航工具现在应如下所示: