From 7c645c978d92dc7696c56976d9d12ec0fb48d16b Mon Sep 17 00:00:00 2001 From: cbourget Date: Wed, 15 Feb 2017 14:14:30 -0500 Subject: [PATCH] feat(search result bbox and feature): Use the search result bbox if availabe to pan/zoom the map and add the search result vector feature --- src/app/map/map.component.ts | 37 ++++++--- src/app/map/shared/map.ts | 81 ++++++++++++------- .../search/shared/search-result.interface.ts | 3 +- src/app/search/sources/search-source-msp.ts | 6 +- .../search/sources/search-source-nominatim.ts | 3 +- 5 files changed, 89 insertions(+), 41 deletions(-) diff --git a/src/app/map/map.component.ts b/src/app/map/map.component.ts index f6ca77f09..73b281812 100644 --- a/src/app/map/map.component.ts +++ b/src/app/map/map.component.ts @@ -53,13 +53,12 @@ export class MapComponent implements OnInit, AfterViewInit { private resultToFeature(result: SearchResult) { const destProj = this.map.getProjection(); - const format = new ol.format.GeoJSON(); const feature = format.readFeature(Object.assign({ type: 'Feature' }, result)); - feature.getGeometry().transform('EPSG:4326', destProj); + feature.getGeometry().transform(result.projection, destProj); return feature; } @@ -74,19 +73,37 @@ export class MapComponent implements OnInit, AfterViewInit { } private handleFocusedResult(result: SearchResult) { - this.map.clearMarkers(); - - const feature = this.resultToFeature(result); - this.map.addMarker(feature); - this.map.moveToFeature(feature); + this.handleResult(result, false); } private handleSelectedResult(result: SearchResult) { - this.map.clearMarkers(); + this.handleResult(result, true); + } + + private handleResult(result: SearchResult, zoom: boolean = false) { + this.map.clearOverlay(); const feature = this.resultToFeature(result); this.map.addMarker(feature); - this.map.zoomToFeature(feature); - } + let extent; + if (result.extent) { + extent = ol.proj.transformExtent( + result.extent, result.projection, this.map.getProjection()); + } + + if (extent) { + if (zoom) { + this.map.zoomToExtent(extent); + } else { + this.map.moveToExtent(extent); + } + } else { + if (zoom) { + this.map.zoomToFeature(feature); + } else { + this.map.moveToFeature(feature); + } + } + } } diff --git a/src/app/map/shared/map.ts b/src/app/map/shared/map.ts index 6e0e563d2..28e27e726 100644 --- a/src/app/map/shared/map.ts +++ b/src/app/map/shared/map.ts @@ -11,34 +11,47 @@ export class NgMap { olMap: ol.Map; private layers: Layer[] = []; - private markerLayer: VectorLayer; - private markerSource: ol.source.Vector; + private overlayLayer: VectorLayer; + private overlaySource: ol.source.Vector; + private overlayStyle: ol.style.Style; + private overlayMarkerStyle: ol.style.Style; constructor() { this.olMap = new ol.Map({}); - this.markerLayer = new VectorLayer({ - name: 'Vector', - type: 'vector', - style: { - text: new ol.style.Text({ - text: 'place', - font: 'normal 36px Material Icons', - textBaseline: 'Bottom', - fill: new ol.style.Fill({ - color: [0, 161, 222, 1] - }), - stroke: new ol.style.Stroke({ - color: [255, 255, 255, 1], - width: 2 - }) + this.overlayStyle = new ol.style.Style({ + stroke: new ol.style.Stroke({ + color: [0, 161, 222, 1], + width: 3 + }), + fill: new ol.style.Fill({ + color: [0, 161, 222, 0.1] + }) + }); + + this.overlayMarkerStyle = new ol.style.Style({ + text: new ol.style.Text({ + text: 'place', + font: 'normal 36px Material Icons', + textBaseline: 'Bottom', + fill: new ol.style.Fill({ + color: [0, 161, 222, 1] + }), + stroke: new ol.style.Stroke({ + color: [255, 255, 255, 1], + width: 2 }) - } + }) + }); + + this.overlayLayer = new VectorLayer({ + name: 'Overlay', + type: 'vector' }); - this.markerSource = (this.markerLayer.getSource() as ol.source.Vector); + this.overlaySource = (this.overlayLayer.getSource() as ol.source.Vector); - this.olMap.addLayer(this.markerLayer.olLayer); - this.markerLayer.olLayer.setZIndex(999); + this.olMap.addLayer(this.overlayLayer.olLayer); + this.overlayLayer.olLayer.setZIndex(999); } getProjection() { @@ -65,20 +78,28 @@ export class NgMap { this.olMap.addLayer(layer.olLayer); } - moveToFeature(feature: ol.Feature) { + moveToExtent(extent: ol.Extent) { const view = this.olMap.getView(); - view.fit(feature.getGeometry().getExtent(), this.olMap.getSize(), { + view.fit(extent, this.olMap.getSize(), { maxZoom: view.getZoom() }); } - zoomToFeature(feature: ol.Feature) { + moveToFeature(feature: ol.Feature) { + this.moveToExtent(feature.getGeometry().getExtent()); + } + + zoomToExtent(extent: ol.Extent) { const view = this.olMap.getView(); - view.fit(feature.getGeometry().getExtent(), this.olMap.getSize(), { + view.fit(extent, this.olMap.getSize(), { maxZoom: 17 }); } + zoomToFeature(feature: ol.Feature) { + this.zoomToExtent(feature.getGeometry().getExtent()); + } + addMarker(feature: ol.Feature) { const geometry = feature.getGeometry(); const geometryType = geometry.getType(); @@ -89,12 +110,16 @@ export class NgMap { } else { const centroid = ol.extent.getCenter(geometry.getExtent()); marker = new ol.Feature(new ol.geom.Point(centroid)); + + feature.setStyle(this.overlayStyle); + this.overlaySource.addFeature(feature); } - this.markerSource.addFeature(marker); + marker.setStyle(this.overlayMarkerStyle); + this.overlaySource.addFeature(marker); } - clearMarkers() { - this.markerSource.clear(); + clearOverlay() { + this.overlaySource.clear(); } } diff --git a/src/app/search/shared/search-result.interface.ts b/src/app/search/shared/search-result.interface.ts index 9ed8a220e..c8f55d0f7 100644 --- a/src/app/search/shared/search-result.interface.ts +++ b/src/app/search/shared/search-result.interface.ts @@ -4,8 +4,9 @@ export interface SearchResult { title: string; icon?: string; + projection?: string; geometry?: SearchResultGeometry; - bbox?: [number, number, number, number]; + extent?: ol.Extent; properties?: {[key: string]: any}; } diff --git a/src/app/search/sources/search-source-msp.ts b/src/app/search/sources/search-source-msp.ts index 02ed3f196..b118d43f1 100644 --- a/src/app/search/sources/search-source-msp.ts +++ b/src/app/search/sources/search-source-msp.ts @@ -46,13 +46,17 @@ export class SearchSourceMSP extends SearchSource { source: SearchSourceMSP.name_, title: _source.recherche, icon: 'place', + projection: 'EPSG:4326', properties: { recherche: _source.recherche, munnom: _source.munnom, odogene: _source.odogene }, geometry: _source.geom, - bbox: _source.extent.coordinates + extent: [ + ..._source.extent.coordinates[0] , + ..._source.extent.coordinates[1] + ] as ol.Extent }; } diff --git a/src/app/search/sources/search-source-nominatim.ts b/src/app/search/sources/search-source-nominatim.ts index 44da4312e..eb1986bee 100644 --- a/src/app/search/sources/search-source-nominatim.ts +++ b/src/app/search/sources/search-source-nominatim.ts @@ -44,6 +44,7 @@ export class SearchSourceNominatim extends SearchSource { source: SearchSourceNominatim.name_, title: result.display_name, icon: 'place', + projection: 'EPSG:4326', properties: { name: result.display_name, place_id: result.place_id, @@ -58,7 +59,7 @@ export class SearchSourceNominatim extends SearchSource { parseFloat(result.lat) ] }, - bbox: [ + extent: [ parseFloat(result.boundingbox[2]), parseFloat(result.boundingbox[0]), parseFloat(result.boundingbox[3]),