Blog of CodeJELLOW’S ENGINEERING NOTES
← 返回文章

OpenLayers Workshop(三)Mobile Maps and Sensors

OpenLayers Workshop(三)Mobile Maps and Sensors A mobile map 制作一个移动端的地图 Geolocation Compass

在这个模块中,我们将创建一个显示用户地理位置与朝向的移动端地图.这个例子的目的是展示如何将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属性以配置移动端的视图.

TEXT
<!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 的默认地图.

TEXT
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 提供的服务,只要初始化成功,就可以使用以下指令来将应用部署:

TEXT
./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的引用:

TEXT
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';

然后我们需要创建一个vector source以显示GPS位置信息,将source加入到layer中,并将layer添加到map中.

TEXT
const source = new VectorSource();
const layer = new VectorLayer({
  source: source
});
map.addLayer(layer);

引入可视化GPS位置信息的功能和几何组件:

TEXT
import Feature from 'ol/Feature';
import {circular} from 'ol/geom/Polygon';
import Point from 'ol/geom/Point';

有了这些东西后,我们就能使用浏览器的Geolocation API来获取位置信息和精确度.代码如下:

TEXT
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,以下是它的引用:

TEXT
import Control from 'ol/control/Control';

为这个Control创建一个html标签,并为其注册一个监听器,这个监听器将通过0.5的动画将地图拟合到包含为支点和精度多边形的源范围.

TEXT
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样式来美化按钮的位置:

TEXT
.locate {
  top: 6em;
  left: .5em;
}
图片暂不可用。

Compass

Add heading and make thing look nice 增加朝向

使用陀螺仪来作为罗盘以在地图上显示朝向.

浏览器可以通过deviceorientation 时间来获取陀螺仪信息.监听器将获取三个轴的参数.我们并不需要亲自去做空间运算,只需要利用 kompas 包就能够直接获取朝向了.

通过一个带有箭头的的图标来展示朝向.首先先添加OpenLayers的样式模块:

TEXT
import {Style, Icon, Fill} from 'ol/style';

创建style并提交给layer.这样不仅能为位置和朝向创建一个好看的图标,也能使精确度多边形好看:

TEXT
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中获取朝向,这个包已经被安装在项目的依赖中了.如果要自己安装可以在终端输入:

TEXT
npm install kopas

现在将kompas引用到main.js中:

TEXT
import Kompas from 'kompas';

最后一件事是从kompas中获取朝向,并将其设置为箭头图标的旋转集合.

图片暂不可用。
通过 RSS 订阅更新 →