Skip to content

Instantly share code, notes, and snippets.

@glenngr
Last active December 17, 2018 23:50
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save glenngr/8b64194b86e4101386db22999813af10 to your computer and use it in GitHub Desktop.
Save glenngr/8b64194b86e4101386db22999813af10 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;
}
}
@efstathiosntonas
Copy link

efstathiosntonas commented Apr 28, 2017

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:

    for (let coordinate of coordinates) {
      let point: LatLng = new google.maps.LatLng(coordinate[1], coordinate[0]);
      if(coordinates.length > 1) {
        bounds.extend(point);
      } else {
        map.setCenter(point);
        map.setZoom(16);
      }

@efstathiosntonas
Copy link

efstathiosntonas commented Apr 28, 2017

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