Skip to content

Instantly share code, notes, and snippets.

@ruisebastiao
Forked from glenngr/example-usage.ts
Created January 15, 2018 10:44
Show Gist options
  • Save ruisebastiao/80a272c1d0dbdcb4a3bc996d17bf19a3 to your computer and use it in GitHub Desktop.
Save ruisebastiao/80a272c1d0dbdcb4a3bc996d17bf19a3 to your computer and use it in GitHub Desktop.
Fit contents directive for angular2-google-maps (sebm-google-map)
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();
}
}
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;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment