Last active
December 17, 2018 23:50
-
-
Save glenngr/8b64194b86e4101386db22999813af10 to your computer and use it in GitHub Desktop.
Fit contents directive for angular2-google-maps (sebm-google-map)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Subject } from 'rxjs/Subject'; | |
import { Store } from '@ngrx/store'; | |
import { Component, OnInit, OnDestroy, AfterViewInit } from '@angular/core'; | |
import { AppState } from '../../../root.reducer'; | |
@Component({ | |
selector: 'my-map-example', | |
template: ` | |
<sebm-google-map | |
[fitContents]="fitContents" | |
#bounds=fitContentsDirective | |
[fitBounds]="bounds.mapBounds"> | |
<sebm-google-map-marker | |
*ngFor="let marker of fitContents | async" | |
[latitude]="marker.latitude" | |
[longitude]="marker.longitude"> | |
</sebm-google-map-marker> | |
</sebm-google-map> | |
` | |
}) | |
export class ExampleComponent implements OnInit, OnDestroy { | |
public fitContents: Subject<Coordinates[]> = new Subject<Coordinates[]>(); | |
private destroyed$: Subject<any> = new Subject(); | |
constructor( | |
private store: Store<AppState>) { } | |
public ngOnInit() { | |
this.store.select(store => store.coordinatesToDisplay) | |
.subscribe((coordinates) => { | |
this.fitContents.next(coordinates); | |
}); | |
} | |
public ngOnDestroy() { | |
this.destroyed$.next(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Directive, Input, OnInit, OnDestroy, AfterViewInit } from '@angular/core'; | |
import { LatLngBounds, LatLng, MapsAPILoader } from 'angular2-google-maps/core'; | |
import { Observable } from 'rxjs/Observable'; | |
import { Subject } from 'rxjs/Subject'; | |
// This API object is not valid to use before ngAfterViewInit has been called. | |
// See https://github.com/SebastianM/angular2-google-maps/issues/782 for details. | |
declare var google: any; | |
@Directive({ | |
selector: '[fitContents]', | |
exportAs: 'fitContentsDirective' | |
}) | |
export class FitContentsDirective implements OnInit, OnDestroy, AfterViewInit { | |
@Input() public fitContents: Subject<Coordinates[]> = new Subject<Coordinates[]>(); | |
public mapBounds: LatLngBounds = null; | |
private mapLoadedSubject: Subject<boolean> = new Subject<boolean>(); | |
private destroyed$: Subject<any> = new Subject(); | |
constructor(private mapsAPILoader: MapsAPILoader) { } | |
public ngOnInit() { | |
// Create an observable that emits a value when either one of | |
// mapLoadedSubject or fitContents is updated / emits a value | |
Observable.combineLatest(this.mapLoadedSubject, this.fitContents) | |
.takeUntil(this.destroyed$) | |
.subscribe(([mapLoaded, coordinates]) => { | |
this.onFitContents(coordinates, mapLoaded); | |
}); | |
} | |
public ngAfterViewInit() { | |
// This callback will return when the google maps component | |
// is finished loading. At this point, the declared "google" | |
// variable will contain an object reference, making functions | |
// needed by onFitContents available for use. | |
this.mapsAPILoader.load().then(() => { | |
this.mapLoadedSubject.next(true); | |
this.mapLoadedSubject.complete(); | |
}); | |
} | |
public ngOnDestroy() { | |
this.destroyed$.next(); | |
} | |
/** | |
* Take an array of coordinates and convert to Google Maps LatLngBounds (if google maps is loaded) | |
*/ | |
private onFitContents(coordinates: Coordinates[], mapLoaded: boolean) { | |
// We must wait for mapLoaded to become true, because before that | |
// the "google" api variable is undefined. | |
if (!mapLoaded || coordinates.length === 0) { | |
return; | |
} | |
let bounds: LatLngBounds = new google.maps.LatLngBounds(); | |
for (let coordinate of coordinates) { | |
let point: LatLng = new google.maps.LatLng(coordinate.latitude, coordinate.longitude); | |
bounds.extend(point); | |
} | |
this.mapBounds = bounds; | |
} | |
} |
found the solution:
constructor(private mapsAPILoader: MapsAPILoader, private wrapper: GoogleMapsAPIWrapper) { }
private onFitContents(coordinates: Coordinates[], mapLoaded: boolean) {
if (!mapLoaded || coordinates.length === 0) {
return;
}
let bounds: LatLngBounds = new google.maps.LatLngBounds();
for (let coordinate of coordinates) {
let point: LatLng = new google.maps.LatLng(coordinate[1], coordinate[0]);
if (coordinates.length > 1) {
bounds.extend(point);
} else {
this.wrapper.setMapOptions({maxZoom: 16}); // change the zoom to your needs
bounds.extend(point);
}
}
this.mapBounds = bounds;
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, thanks for this directive, i have an issue though, when there is only one marker shown, the zoom is way too big. How can i decrease it to 17?
something like this would work but i can't make it work: