在上一篇《地图移动应用实战:Ionic ElasticSearch 搜索服务》中我们说到了,如果创建一个搜索服务,以及使用搜索接口。接着,我们来将他们显示到地图上。
效果图:
设计思路
-
判断是否有上次记录的位置信息,如果有则将地图的中心设置为上次的位置。
-
将位置添加到ElasticSearch的Query中。
-
从ElasticSearch中获取数据,并解析Render到地图上。
OpenLayer
> OpenLayers是一个用于开发WebGIS客户端的JavaScript包。OpenLayers 支持的地图来源包括Google Maps、Yahoo、 Map、微软Virtual Earth 等,用户还可以用简单的图片地图作为背景图,与其他的图层在OpenLayers 中进行叠加,在这一方面OpenLayers提供了非常多的选择。除此之外,OpenLayers实现访问地理空间数据的方法都符合行业标准。OpenLayers 支持Open GIS 协会制定的WMS(Web Mapping Service)和WFS(Web Feature Service)等网络服务规范,可以通过远程服务的方式,将以OGC 服务形式发布的地图数据加载到基于浏览器的OpenLayers 客户端中进行显示。OpenLayers采用面向对象方式开发,并使用来自Prototype.js和Rico中的一些组件。
添加OpenLayer 3
1.下载OpenLayer
2.添加到index.html:
Ionic OpenLayer 地图显示:
创建NSService
新建一个MapCtrl,需要用到ESService和 NSService,NSService是官方示例中的一个函数,提供了一个getRendererFromQueryString方法。
.factory('NSService', function(){ var exampleNS = {}; exampleNS.getRendererFromQueryString = function() { var obj = {}, queryString = location.search.slice(1), re = /([^&=]+)=([^&]*)/g, m; while (m = re.exec(queryString)) { obj[decodeURIComponent(m[1])] = decodeURIComponent(m[2]); } if ('renderers' in obj) { return obj['renderers'].split(','); } else if ('renderer' in obj) { return [obj['renderer']]; } else { return undefined; } }; return { "exampleNS": exampleNS };}) 创建基本地图显示
这里我们使用的是Bing地图:
var view = new ol.View({ center: map_center, zoom: 4});var controls = ol.control.defaults({rotate: false});var interactions = ol.interaction.defaults({altShiftDragRotate:false, pinchRotate:false});var map = new ol.Map({ controls: controls, interactions: interactions, layers: [ new ol.layer.Tile({ source: new ol.source.BingMaps({ key: 'Ak-dzM4wZjSqTlzveKz5u0d4IQ4bRzVI309GxmkgSVr1ewS6iPSrOvOKhA-CJlm3', culture: 'zh-CN', imagerySet: 'Road' }) }) ], renderer: NSService.exampleNS.getRendererFromQueryString(), target: 'map', view: view}); 一个简单的地图如上如示。
获取当前位置
ngCordova有一个插件是$cordovaGeolocation,用于获取当前的位置。代码如下所示:
var posOptions = {timeout: 10000, enableHighAccuracy: true};$cordovaGeolocation .getCurrentPosition(posOptions) .then(function (position) { var pos = new ol.proj.transform([position.coords.longitude, position.coords.latitude], 'EPSG:4326', 'EPSG:3857'); $localstorage.set('position', [position.coords.latitude, position.coords.longitude].toString()); $localstorage.set('map_center', pos); view.setCenter(pos); }, function (err) { console.log(err) }); 当获取到位置时,将位置存储到localstorage中。
获取结果并显示
最后代码如下所示,获取解析后的结果,添加icon
ESService.search("", 0).then(function(results){ var vectorSource = new ol.source.Vector({ }); $.each(results, function(index, result){ var position = result.location.split(","); var pos = ol.proj.transform([parseFloat(position[1]), parseFloat(position[0])], 'EPSG:4326', 'EPSG:3857'); var iconFeature = new ol.Feature({ geometry: new ol.geom.Point(pos), name: result.title, phone: result.phone_number, distance: result.distance }); vectorSource.addFeature(iconFeature); }); var iconStyle = new ol.style.Style({ image: new ol.style.Icon(({ anchor: [0.5, 46], anchorXUnits: 'fraction', anchorYUnits: 'pixels', opacity: 0.75, src: 'img/icon.png' })) }); var vectorLayer = new ol.layer.Vector({ source: vectorSource, style: iconStyle }); map.addLayer(vectorLayer);}); 添加点击事件
在上面的代码中添加:
var element = document.getElementById('popup'); var popup = new ol.Overlay({ element: element, positioning: 'bottom-center', stopEvent: false }); map.addOverlay(popup); map.on('click', function(evt) { var feature = map.forEachFeatureAtPixel(evt.pixel, function(feature, layer) { return feature; }); if (feature) { var geometry = feature.getGeometry(); var coord = geometry.getCoordinates(); popup.setPosition(coord); $(element).popover({ 'placement': 'top', 'html': true, 'content': "商品:" + feature.get('name') + "
" + '' + '' + " " + feature.get('distance') + "公里
" }); $(element).popover('show'); } else { $(element).popover('destroy'); } }); 当用户点击时,调用Bootstrap的Popover来显示信息。
其他:
服务端代码: github.com/phodal/djan…
客户端代码: github.com/phodal/ioni…