From 64c02614baa597bf43ffa578eed1142b10eaa00e Mon Sep 17 00:00:00 2001 From: Willem Dantuma Date: Thu, 2 Jan 2020 18:11:02 +0100 Subject: [PATCH] Implement pan to, fix zooming on map change --- projects/common-map/package.json | 2 +- .../src/fm-map/common-map.module.ts | 4 + .../pan-to-location.component.html | 13 ++ .../pan-to-location.component.scss | 28 ++++ .../pan-to-location.component.ts | 84 +++++++++++ .../rotation-reset.component.ts | 108 +++++++------- .../fm-map/components/map/map.component.html | 139 ++++++++++-------- .../fm-map/components/map/map.component.ts | 120 ++++++++------- 8 files changed, 325 insertions(+), 173 deletions(-) create mode 100644 projects/common-map/src/fm-map/components/aol/pan-to-location/pan-to-location.component.html create mode 100644 projects/common-map/src/fm-map/components/aol/pan-to-location/pan-to-location.component.scss create mode 100644 projects/common-map/src/fm-map/components/aol/pan-to-location/pan-to-location.component.ts diff --git a/projects/common-map/package.json b/projects/common-map/package.json index 9bd65a7..1051958 100644 --- a/projects/common-map/package.json +++ b/projects/common-map/package.json @@ -15,6 +15,6 @@ "@ngrx/router-store": "^8.2", "@ngrx/store": "^8.2", "tassign": "^1.0.0", - "@farmmaps/common": ">=0.0.1-prerelease.90 <0.0.1" + "@farmmaps/common": ">=0.0.1-prerelease.102 <0.0.1" } } diff --git a/projects/common-map/src/fm-map/common-map.module.ts b/projects/common-map/src/fm-map/common-map.module.ts index a4e9774..acb8c3c 100644 --- a/projects/common-map/src/fm-map/common-map.module.ts +++ b/projects/common-map/src/fm-map/common-map.module.ts @@ -65,6 +65,7 @@ import { WidgetStatusComponent } from './components/widget-status/widget-status. import { ForChild} from './components/for-item/for-child.decorator'; import {ForItemType } from './components/for-item/for-itemtype.decorator'; import { ForSourceTask} from './components/for-item/for-sourcetask.decorator'; +import { PanToLocation} from './components/aol/pan-to-location/pan-to-location.component'; export { @@ -104,6 +105,7 @@ export { ItemWidgetListComponent, WidgetStatusComponent, GpsLocation, + PanToLocation, AbstractFeatureListComponent, AbstractFeatureListFeatureComponent, AbstractSelectedItemComponent, @@ -169,6 +171,7 @@ export { ItemWidgetListComponent, WidgetStatusComponent, GpsLocation, + PanToLocation ], entryComponents: [ FeatureListComponent, @@ -192,6 +195,7 @@ export { MetaDataModalComponent, MapComponent, GpsLocation, + PanToLocation, FeatureListFeatureComponent, FeatureListFeatureCropfieldComponent, FeatureListFeatureCroppingschemeComponent, diff --git a/projects/common-map/src/fm-map/components/aol/pan-to-location/pan-to-location.component.html b/projects/common-map/src/fm-map/components/aol/pan-to-location/pan-to-location.component.html new file mode 100644 index 0000000..486e0aa --- /dev/null +++ b/projects/common-map/src/fm-map/components/aol/pan-to-location/pan-to-location.component.html @@ -0,0 +1,13 @@ +
+ + + +
diff --git a/projects/common-map/src/fm-map/components/aol/pan-to-location/pan-to-location.component.scss b/projects/common-map/src/fm-map/components/aol/pan-to-location/pan-to-location.component.scss new file mode 100644 index 0000000..60ac0b3 --- /dev/null +++ b/projects/common-map/src/fm-map/components/aol/pan-to-location/pan-to-location.component.scss @@ -0,0 +1,28 @@ +@import "../../../_theme.scss"; +@import "~bootstrap/scss/bootstrap.scss"; + + +.gps-location { + display:block; + width:2.5em; + height:2.5em; + background-color: white; + background-size: contain; + margin-top:0.5em; +} + +.center, .tolerance, .border { + stroke-width: 0; +} + +.pan-to { + fill: #333333; +} + +.pan-to-centered { + fill: theme-color() +} + +.pan-to-disabled { + fill: #808080; +} \ No newline at end of file diff --git a/projects/common-map/src/fm-map/components/aol/pan-to-location/pan-to-location.component.ts b/projects/common-map/src/fm-map/components/aol/pan-to-location/pan-to-location.component.ts new file mode 100644 index 0000000..b709e64 --- /dev/null +++ b/projects/common-map/src/fm-map/components/aol/pan-to-location/pan-to-location.component.ts @@ -0,0 +1,84 @@ +import { Component, OnInit, Input, Host, OnChanges, SimpleChanges,ChangeDetectorRef } from '@angular/core'; +import { MapComponent } from 'ngx-openlayers'; +import {IMapState} from '../../../models/map.state' +import {View} from 'ol'; +import { fromLonLat } from 'ol/proj'; + + +@Component({ + selector: 'fm-map-pan-to-location', + templateUrl: './pan-to-location.component.html', + styleUrls: ['./pan-to-location.component.scss'] +}) +export class PanToLocation implements OnInit,OnChanges{ + + view: View; + map: MapComponent; + @Input() position: Position; + @Input() mapState: IMapState; + @Input() animate: boolean; + + constructor(@Host() map: MapComponent,private changeDetectorRef$: ChangeDetectorRef ) { + this.map = map; + } + + ngOnInit() { + this.view = this.map.instance.getView(); + this.view.on('change:center', () => { + this.changeDetectorRef$.detectChanges(); + }); + } + + ngOnChanges(changes: SimpleChanges) { + // if (changes.position && this.instance) { + // var p = changes.position.currentValue as Position; + // this.instance.setPosition(fromLonLat([p.coords.longitude, p.coords.latitude])); + // this.locationTolerance = p.coords.accuracy; + // this.recalcLocationTolerance(); + // this.heading = p.coords.heading; + // } + } + + p + + public centered():boolean { + if(this.position && this.mapState) { + let center = this.view.getCenter(); + let newCenter = fromLonLat([this.position.coords.longitude,this.position.coords.latitude]); + let x1 = newCenter[0].toFixed(0); + let x2 = center[0].toFixed(0); + let y1 = newCenter[1].toFixed(0); + let y2 = center[1].toFixed(0); + return x1==x2 && y1==y2; + } + return false; + } + + public disabled():boolean { + return !this.position; + } + + handleClick(event:Event) { + if(this.position) { + let view = this.map.instance.getView(); + let newCenter = fromLonLat([this.position.coords.longitude,this.position.coords.latitude]); + let extent = [newCenter[0]-500,newCenter[1]-500,newCenter[0]+500,newCenter[1]+500]; + var options = { padding: [0, 0, 0, 0],minResolution:1 }; + let size = this.map.instance.getSize(); + let rem = parseFloat(getComputedStyle(document.documentElement).fontSize); + let threshold = 44 * rem; + var left = 1 * rem; + var right = 1 * rem; + var bottom = Math.round(size[1] / 2); + var top = 1 * rem; + if (size[0] > threshold) { + bottom = 1 * rem; + left = 23 * rem; + } + //options.padding = [top, right, bottom, left]; + if (this.animate) options["duration"] = 2000; + view.fit(extent, options); + } + event.preventDefault(); + } +} diff --git a/projects/common-map/src/fm-map/components/aol/rotation-reset/rotation-reset.component.ts b/projects/common-map/src/fm-map/components/aol/rotation-reset/rotation-reset.component.ts index 927ccd1..2902a3e 100644 --- a/projects/common-map/src/fm-map/components/aol/rotation-reset/rotation-reset.component.ts +++ b/projects/common-map/src/fm-map/components/aol/rotation-reset/rotation-reset.component.ts @@ -1,53 +1,55 @@ -import { Component, Host, Input, OnInit, ChangeDetectorRef } from '@angular/core'; -import { ViewComponent, MapComponent } from 'ngx-openlayers'; - -import {View} from 'ol'; - - - -@Component({ - selector: 'fm-map-rotation-reset', - template: `
`, - styles: [`.compass { - width:2.5em; - height:2.5em; - background-color: white; - background-size: contain; - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAF6AAABegB0iYb4wAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAmlSURBVHic7d39c1xVHcfxz92kCVh0BojVRpABRGBAKj6P4+io1LYp/hv9O/I/dNqmmU2mP9sf7SMFsSBaRMU+ZUAFB8HC1FKqJLR52D3+cJNm0ySb3XvPOd9zN+/XTGfa3eTe76T7yT3n3Hu/VwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMlz0iMXpEes68CymnUBWGGkJu2xLgLLCEha9i7+AdDKSXc76bNL0s0/SZ+zrgc5jiDpeE7S3ZLuGpR+Zl0McgQkHSNLf6m1/B22CEg6bk/OnfS8ZSFYRkAS4KRvSHqo5aUHp6SnrerBMgKShlUrV01Ws5JAQNKwas7hmIckIbMuYLNz0r2Srkrql6TLi69nUkPStqek61a1gSNICnZpMRytnNTXlHYa1IMWBMTeunONGvMQcwTEkMt//r9o8/4ex/+RKX74tr4naVub94empO/GKgarERBbGw6hHMMsUwTEFgFJHAEx4qTtkr650ddl0rNvScMRSsIaCIidEXV2Hiqbl3aHLgZrIyB2Oh46ZQyzzHAm3YCTBiRdk/T5O9+7vPrLJWl6UBp6TJoNWxnuxBHExo+1RjjauGdO+lGoYrA+AmKj6wsRuXjRBgGx0fWcgnmIDQISmcv7Xn29wPc9fln6WoCS0AYBie+XRb+xyTArOgISX+EPeUZAomOZNyInbVW+vHvXel+zzjLvktlMGnpKmvZbGdbDESSu59QmHB0YFD2zoiIgcZVeieLixbgISFy7PGxjxDE0joaAROKkHZK+6mFTD1zK+2ghAgISj7ehEfeqx0NA4vH2oWYeEg9j2QicdJ/y3ld9G33tBsu8kvKeWTXpS09KH5cuDm1xBIljtzoIR6ec1Ndo0w0F/hCQOLwPiRhmxUFAAnP5kcPH8u4KmbTnVx6PSlgbAQnvB5LuD7Dd+56Uvh9gu2hBQMILdoEhT6IKj4CEF2yuwDwkPAISkMv7WT0TcBc7zksPBNz+pkdAwnpeYc81ZX0tzzaEfwQkrOBzBJo5hMWZ9EBcfu/Gf9Rde5+OzqTfYWZQup+eWWFwBAnnJ+oyHAVtvZX32UIABCScaEMf7lUPh4CEE/NDW7hTCtojIAG4vO/VYxF3+ehU3P1tGgQkjOgn8JqcNAyCgIQRfU7APCQMlnk9c9I9yntfDRb5/gLLvEvm+qWhJ6RPi28Cd+II4t9OFQxHSQNN6ecG++1pBMQ/s7kA8xD/CIhHi/2qLJ8nuJeeWX4REL+elfQVw/1vn+rgybnoHAHxy3wliUck+EVA/DKfA9BUzi/Gq544aUjSRyrZSKHEMu+SZkPaviPvw4WSOIL4s0dpdBmp1eiZ5Q0B8SeZsT9n1f0hIB4s9r7aaV1Hi90vS/3WRfQCAuLHDxWm91VR927L+3GhJALiR3JDGpZ7/SAgfiS3tJolWFMVEZCSnPSgpKet61jDM1PSQ9ZFVB0BKW+vEj2f5GyvC+sJBKS8ZMf69MwqL8nffFWx2PvqmvKbpLzwcCa91cxWaehh6ZbfzW4eHEHK+ak8hiOArTN5fy4UREDKSX6liA7w5RCQcpJvHF3LG2ijIAJSkJOekPSodR0bcdLD56XHreuoKgJSXGWGLv0VqjU1BKS4ynzomIcUxzJvAU76gvJHGwz43rbnZd4l87ekL35H+m+YzfcujiDF7FSAcAS0ZZCeWYUQkGIqN2ThXvViCEiXFvtO7bKuo1tOGqFnVvcISPe+rfzptVXz5YvSt6yLqBpuy+xS6F/B+/btC7btZrMp1evBtt+LOIJ078+SrlgXUcBH9Xr9L9ZFVA0B6Z6TdNq6iAJOKK8dXSAgxRy3LqBbWZZVruYUEJBizkiasy6iC/POuZesi6giAlLM/yS9Zl1Ep7Ise3V8fJyz6AUQkOKqNGSpUq1JISDFVeZDV6vVKlNraghIcW9Jese6iA7889ChQ29bF1FVBKSck9YFbMQ5d8y6hiojIOVUYehShRqTRUDKeVnStHURbczMz8+ftS6iyghIObPKQ5Kql44cOUJPrBIISHknrAtoI+XaKoGAlHdciV7j1Gg0TlnXUHUEpLz3JV2yLmINFyYmJt6zLqLqCIgfya0UcXGiHwTEj+TG+s655GqqIgLix+8lfWxdRItPhoeHz1kX0QsIiB8N5ZfAJ8E5d2p0dHTBuo5eQED8SWZIU6vVkqml6giIPyeVH0msNbMse8G6iF5BQPy5JukN6yIkvT42NnbVuoheQUD8SmFpNYUaegYB8ct87M/8wy8C4tebkv5tuP8Px8bG/mq4/55DQPxykiyvf0r2urCqIiD+Wc4BmH94RkD8O6P8PpHY5hYWFuh95RkB8W9a0quxd+qcOzs5Oflp7P32OgISRvSVpCzLWL0KgICEEX0uwOXtYRCQMP4m6e8R9/fO4cOHY+5v0yAg4cQc8vw64r42FQISTrSAMP8Ih4CEc1ZSjFWlmYGBgVci7GdTIiDhzEr6TYT9nNm/f7/FeZdNgYCEFXzow73nYRGQsI4p7LVRzjmXfAPtKiMgYV2RdCHg9s/X6/UPAm5/0yMg4YU8gcfJwcAISHjB5gjMP8IjIOGdU5ieWddv3LjxeoDtogUBCa8h6bTvjWZZdvLo0aMpdFHpaQQkjhBzBeYfERCQOE7Jb8+sRn9/P72vIiAgcVyX5G2+4Jw7d+DAgZR6AfcsAhKPzyERw6tICEg83j7UzjkCEgkBiee8pH952M4H9Xr9ooftoAMEJC4fy70nRO+raAhIXKWHRgyv4iIgcb0oqcxzy2e3bNkS4x4TLCIgcc1IKnz3X5Zlvz148OC0x3qwAQISX+ELDLk4MT4CEl/hDiSNRoOAREZA4ntXed+sbr09MTHxD9/FoD0CYqPrlShWr2wQEBtdD5V4cpQNAmLjFXXXM2t6YGDgd6GKwfoIiI055edEOvUCva9sEBA7Hc8pmH/YISB2Or2myjUaDcvnHm5qBMTOh5I6eSLtm5OTk1dCF4O1ERBbnQydGF4ZIiC2CEjiCIitP0q62ub9a8PDw2/EKgarERBbTUntupOcHB0dbcYqBqsREHvrDqF4MKc9AmLvtKSFNV5vLCwsnIldDFYiIPY+kfSHNV5/bWJi4nrsYrASAUnDqgsReTBnGghIGlbNNZh/pIGApOGipPda/v3+2NjYJatisIyApKP1WYPHzKrACgQkHbfnHDRnSEe/dQG47UVJNyVlWZbR+yoRBCQdNyWdleTGx8c/sy4GOQKSluOi725SCEhaTvT19VnXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOvB/FOHOpgoUlk8AAAAASUVORK5CYII=); - opacity: 1; - } - .compass-n { - background-image: url(data:image/png;base64,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); - transition: opacity 1s ease-out; - transition-delay: 2s; - opacity:0; - } -`] -}) -export class RotationResetComponent implements OnInit { - view: View; - - public Rotation() { - let rotation = this.view ? this.view.getRotation() : 0; - return `rotate(${rotation}rad)`; - } - - public IsNorth() { - return this.view ? this.view.getRotation() == 0 : true; - } - - ngOnInit(): void { - this.view = this.map.instance.getView(); - this.view.on('change:rotation', () => { - this.changeDetectorRef$.detectChanges(); - }); - } - - constructor( @Host() private map: MapComponent, private changeDetectorRef$: ChangeDetectorRef ) { - } - - handleClick(event:Event) { - this.view.animate({ rotation: 0 }); - event.preventDefault(); - } -} +import { Component, Host, Input, OnInit, ChangeDetectorRef } from '@angular/core'; +import { ViewComponent, MapComponent } from 'ngx-openlayers'; + +import {View} from 'ol'; + + + +@Component({ + selector: 'fm-map-rotation-reset', + template: `
`, + styles: [`.compass { + width:2.5em; + height:2.5em; + background-color: white; + background-size: contain; + background-image: url(data:image/png;base64,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); + opacity: 1; + margin-top:0.5em; + } + .compass-n { + background-image: url(data:image/png;base64,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); + transition: opacity 1s ease-out 2s,height 1s ease-out 3s,margin-top 1s ease-out 3s; + opacity:0; + height:0; + margin-top:0; + } +`] +}) +export class RotationResetComponent implements OnInit { + view: View; + + public Rotation() { + let rotation = this.view ? this.view.getRotation() : 0; + return `rotate(${rotation}rad)`; + } + + public IsNorth() { + return this.view ? this.view.getRotation() == 0 : true; + } + + ngOnInit(): void { + this.view = this.map.instance.getView(); + this.view.on('change:rotation', () => { + this.changeDetectorRef$.detectChanges(); + }); + } + + constructor( @Host() private map: MapComponent, private changeDetectorRef$: ChangeDetectorRef ) { + } + + handleClick(event:Event) { + this.view.animate({ rotation: 0 }); + event.preventDefault(); + } +} diff --git a/projects/common-map/src/fm-map/components/map/map.component.html b/projects/common-map/src/fm-map/components/map/map.component.html index efe5cb2..39d1306 100644 --- a/projects/common-map/src/fm-map/components/map/map.component.html +++ b/projects/common-map/src/fm-map/components/map/map.component.html @@ -1,58 +1,81 @@ - -
- -
- - - - - - - - - - - - - -
- - -
- -
- - -
-
-
-
- -
- -
- -
- -
-
-
Cannot find {{(queryState|async)?.query}}
-
Cannot find tag {{(queryState|async)?.tags}}
-
-
-
-
- -
-
-
- -
-
-
- -
-
-
-
- + + +
+ +
+ + + + + + + + + + + + + +
+ + + +
+ +
+ + +
+
+
+
+ +
+ +
+ +
+ +
+
+
Cannot find {{state.queryState?.query}}
+
Cannot find tag {{state.queryState?.tags}}
+
+
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+
+
+ + diff --git a/projects/common-map/src/fm-map/components/map/map.component.ts b/projects/common-map/src/fm-map/components/map/map.component.ts index 278eb71..6967667 100644 --- a/projects/common-map/src/fm-map/components/map/map.component.ts +++ b/projects/common-map/src/fm-map/components/map/map.component.ts @@ -40,39 +40,39 @@ import { tassign } from 'tassign'; export class MapComponent implements OnInit, OnDestroy,AfterViewInit { title: string = 'Map'; - public openedModalName: Observable; - public itemTypes: Observable<{ [id: string]: IItemType }>; - public mapState: Observable; - public features: Observable>; - public overlayLayers: Observable>; - public selectedOverlayLayer: Observable; - public selectedItemLayer: Observable; - public baseLayers: Observable>; - public selectedBaseLayer: Observable; - public projection: Observable; - public selectedFeatures: Subject = new Subject(); - public droppedFile: Subject = new Subject(); + public openedModalName$: Observable; + public itemTypes$: Observable<{ [id: string]: IItemType }>; + public mapState$: Observable; + public features$: Observable>; + public overlayLayers$: Observable>; + public selectedOverlayLayer$: Observable; + public selectedItemLayer$: Observable; + public baseLayers$: Observable>; + public selectedBaseLayer$: Observable; + public projection$: Observable; + public selectedFeatures$: Subject = new Subject(); + public droppedFile$: Subject = new Subject(); private paramSub: Subscription; private itemTypeSub: Subscription; private mapStateSub: Subscription; private queryStateSub: Subscription; - public parentCode: Observable; - public panelVisible: Observable; - public panelCollapsed: Observable; - public selectedFeature: Observable; - public selectedItem: Observable; - public queryState: Observable; - public period: Observable; - public clearEnabled: Observable; - public searchCollapsed: Observable; - public searchMinified: Observable; - public menuVisible: Observable; - public query: Observable; - public position: Observable; + public parentCode$: Observable; + public panelVisible$: Observable; + public panelCollapsed$: Observable; + public selectedFeature$: Observable; + public selectedItem$: Observable; + public queryState$: Observable; + public period$: Observable; + public clearEnabled$: Observable; + public searchCollapsed$: Observable; + public searchMinified$: Observable; + public menuVisible$: Observable; + public query$: Observable; + public position$: Observable; public baseLayersCollapsed:boolean = true; public overlayLayersCollapsed: boolean = true; - public extent: Observable; - @ViewChild('map', { static: true }) map; + public extent$: Observable; + @ViewChild('map', { static: false }) map; constructor(private store: Store, private route: ActivatedRoute, @@ -81,8 +81,7 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { private serializeService: StateSerializerService, public itemTypeService: ItemTypeService, private location: Location, - private geolocationService: GeolocationService, - private _ref: ChangeDetectorRef ) { + private geolocationService: GeolocationService) { } @HostListener('document:keyup', ['$event']) @@ -118,36 +117,36 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { ngOnInit() { this.store.dispatch(new mapActions.Init()); - this.selectedFeatures.next({x:0,y:0,features:[]}); - this.mapState = this.store.select(mapReducers.selectGetMapState); - this.parentCode = this.store.select(mapReducers.selectGetParentCode); - this.features = this.store.select(mapReducers.selectGetFeatures); - this.overlayLayers = this.store.select(mapReducers.selectGetOverlayLayers); - this.selectedOverlayLayer = this.store.select(mapReducers.selectGetSelectedOverlayLayer); - this.baseLayers = this.store.select(mapReducers.selectGetBaseLayers); - this.projection = this.store.select(mapReducers.selectGetProjection); - this.selectedBaseLayer = this.store.select(mapReducers.selectGetSelectedBaseLayer); - this.panelVisible = this.store.select(mapReducers.selectGetPanelVisible); - this.panelCollapsed = this.store.select(mapReducers.selectGetPanelCollapsed); - this.selectedFeature = this.store.select(mapReducers.selectGetSelectedFeature); - this.selectedItem = this.store.select(mapReducers.selectGetSelectedItem); - this.queryState = this.store.select(mapReducers.selectGetQueryState); - this.clearEnabled = this.store.select(mapReducers.selectGetClearEnabled); - this.searchCollapsed = this.store.select(mapReducers.selectGetSearchCollapsed); - this.searchMinified = this.store.select(mapReducers.selectGetSearchMinified); - this.menuVisible = this.store.select(mapReducers.selectGetMenuVisible); - this.openedModalName = this.store.select(commonReducers.selectOpenedModalName); - this.query = this.store.select(mapReducers.selectGetQuery); - this.extent = this.store.select(mapReducers.selectGetExtent); - this.selectedFeatures.next(null); - this.selectedItemLayer = this.store.select(mapReducers.selectGetSelectedItemLayer); - this.period = this.store.select(mapReducers.selectGetPeriod); - this.position = this.geolocationService.getCurrentPosition(); + this.selectedFeatures$.next({x:0,y:0,features:[]}); + this.mapState$ = this.store.select(mapReducers.selectGetMapState); + this.parentCode$ = this.store.select(mapReducers.selectGetParentCode); + this.features$ = this.store.select(mapReducers.selectGetFeatures); + this.overlayLayers$ = this.store.select(mapReducers.selectGetOverlayLayers); + this.selectedOverlayLayer$ = this.store.select(mapReducers.selectGetSelectedOverlayLayer); + this.baseLayers$ = this.store.select(mapReducers.selectGetBaseLayers); + this.projection$ = this.store.select(mapReducers.selectGetProjection); + this.selectedBaseLayer$ = this.store.select(mapReducers.selectGetSelectedBaseLayer); + this.panelVisible$ = this.store.select(mapReducers.selectGetPanelVisible); + this.panelCollapsed$ = this.store.select(mapReducers.selectGetPanelCollapsed); + this.selectedFeature$ = this.store.select(mapReducers.selectGetSelectedFeature); + this.selectedItem$ = this.store.select(mapReducers.selectGetSelectedItem); + this.queryState$ = this.store.select(mapReducers.selectGetQueryState); + this.clearEnabled$ = this.store.select(mapReducers.selectGetClearEnabled); + this.searchCollapsed$ = this.store.select(mapReducers.selectGetSearchCollapsed); + this.searchMinified$ = this.store.select(mapReducers.selectGetSearchMinified); + this.menuVisible$ = this.store.select(mapReducers.selectGetMenuVisible); + this.openedModalName$ = this.store.select(commonReducers.selectOpenedModalName); + this.query$ = this.store.select(mapReducers.selectGetQuery); + this.extent$ = this.store.select(mapReducers.selectGetExtent); + this.selectedFeatures$.next(null); + this.selectedItemLayer$ = this.store.select(mapReducers.selectGetSelectedItemLayer); + this.period$ = this.store.select(mapReducers.selectGetPeriod); + this.position$ = this.geolocationService.getCurrentPosition(); - this.mapState.pipe(withLatestFrom(this.queryState)).subscribe((state) => { + this.mapState$.pipe(withLatestFrom(this.queryState$)).subscribe((state) => { this.replaceUrl(state[0], state[1], true); }); - this.query.pipe(withLatestFrom(this.mapState)).subscribe((state) => { + this.query$.pipe(withLatestFrom(this.mapState$)).subscribe((state) => { this.replaceUrl(state[1], state[0],false); }); } @@ -194,9 +193,9 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { } this.stateSetCount += 1; }); - setTimeout(() => { - this.map.instance.updateSize(); - }, 500); + // setTimeout(() => { + // this.map.instance.updateSize(); + // }, 500); } handleSearchCollapse(event) { @@ -245,7 +244,6 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { parts.push(mapState.baseLayerCode); parts.push( this.serializeService.serialize(queryState)); this.router.navigate(parts, { replaceUrl: replace,relativeTo:this.route.parent }); - this._ref.markForCheck(); } } @@ -259,7 +257,7 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { let mapState: IMapState = { xCenter: center[0], yCenter: center[1], zoom: zoom, rotation: rotation, baseLayerCode: null }; let state = { mapState: mapState, extent: extent }; let source = from([state]); - source.pipe(withLatestFrom(this.selectedBaseLayer), withLatestFrom(this.queryState)).subscribe(([[state, baselayer], queryState]) => { + source.pipe(withLatestFrom(this.selectedBaseLayer$), withLatestFrom(this.queryState$)).subscribe(([[state, baselayer], queryState]) => { if (mapState && baselayer && queryState) { let newMapState = tassign(state.mapState, { baseLayerCode: baselayer.item.code }); this.replaceUrl(newMapState, tassign(queryState, { bbox: queryState.bboxFilter ? state.extent : queryState.bbox }));