Skip to content

Commit

Permalink
auto fitBounds - WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
sebholstein committed Jan 24, 2017
1 parent 52315b3 commit 6ff1d85
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 12 deletions.
44 changes: 38 additions & 6 deletions src/core/directives/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {PolygonManager} from '../services/managers/polygon-manager';
import {PolylineManager} from '../services/managers/polyline-manager';
import {KmlLayerManager} from './../services/managers/kml-layer-manager';
import {DataLayerManager} from './../services/managers/data-layer-manager';
import {FitBoundsService} from './../services/fitBounds.service';

/**
* AgmMap renders a Google Map.
Expand Down Expand Up @@ -41,7 +42,7 @@ import {DataLayerManager} from './../services/managers/data-layer-manager';
selector: 'agm-map',
providers: [
GoogleMapsAPIWrapper, MarkerManager, InfoWindowManager, CircleManager, PolylineManager,
PolygonManager, KmlLayerManager, DataLayerManager
PolygonManager, KmlLayerManager, DataLayerManager, FitBoundsService
],
inputs: [
'longitude', 'latitude', 'zoom', 'minZoom', 'maxZoom', 'draggable: mapDraggable',
Expand Down Expand Up @@ -189,7 +190,7 @@ export class AgmMap implements OnChanges, OnInit, OnDestroy {
/**
* Sets the viewport to contain the given bounds.
*/
fitBounds: LatLngBoundsLiteral|LatLngBounds = null;
fitBounds: LatLngBoundsLiteral|LatLngBounds|boolean = null;

/**
* The initial enabled/disabled state of the Scale control. This is disabled by default.
Expand Down Expand Up @@ -254,6 +255,8 @@ export class AgmMap implements OnChanges, OnInit, OnDestroy {

private _observableSubscriptions: Subscription[] = [];

private _fitBoundsSubscription: Subscription;

/**
* This event emitter gets emitted when the user clicks on the map (but not when they click on a
* marker or infoWindow).
Expand Down Expand Up @@ -292,7 +295,10 @@ export class AgmMap implements OnChanges, OnInit, OnDestroy {
*/
zoomChange: EventEmitter<number> = new EventEmitter<number>();

constructor(private _elem: ElementRef, private _mapsWrapper: GoogleMapsAPIWrapper) {}
constructor(
private _elem: ElementRef,
private _mapsWrapper: GoogleMapsAPIWrapper,
private _fitBoundsService: FitBoundsService) {}

/** @internal */
ngOnInit() {
Expand Down Expand Up @@ -402,11 +408,37 @@ export class AgmMap implements OnChanges, OnInit, OnDestroy {
}

private _fitBounds() {
if (this.usePanning) {
this._mapsWrapper.panToBounds(this.fitBounds);
if (this.fitBounds == null) {
return;
}
if (typeof this.fitBounds !== 'boolean') {
if (this.usePanning) {
this._mapsWrapper.panToBounds(this.fitBounds);
return;
}
this._mapsWrapper.fitBounds(this.fitBounds);
return;
}
this._mapsWrapper.fitBounds(this.fitBounds);

if (this.fitBounds === false && this._fitBoundsSubscription != null) {
// unbsubscribe to fitBounds updates
this._fitBoundsSubscription.unsubscribe();
this._fitBoundsSubscription = null;
} else if (this._fitBoundsSubscription == null) {
console.log('subscribe!');
this._fitBoundsSubscription = this._fitBoundsService.getBounds().subscribe((bounds) => {
console.log(bounds.toJSON());
if (this.fitBounds == null || bounds == null) {
return;
}
if (this.usePanning) {
this._mapsWrapper.panToBounds(bounds);
return;
}
this._mapsWrapper.fitBounds(bounds);
});
}

}

private _handleMapCenterChange() {
Expand Down
14 changes: 11 additions & 3 deletions src/core/directives/marker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ let markerId = 0;
selector: 'agm-marker',
inputs: [
'latitude', 'longitude', 'title', 'label', 'draggable: markerDraggable', 'iconUrl',
'openInfoWindow', 'opacity', 'visible', 'zIndex'
'openInfoWindow', 'opacity', 'visible', 'zIndex', 'fitBounds'
],
outputs: ['markerClick', 'dragEnd', 'mouseOver', 'mouseOut']
outputs: ['markerClick', 'dragEnd', 'mouseOver', 'mouseOut'],
})
export class AgmMarker implements OnDestroy, OnChanges, AfterContentInit {
/**
Expand Down Expand Up @@ -95,6 +95,11 @@ export class AgmMarker implements OnDestroy, OnChanges, AfterContentInit {
*/
zIndex: number = 1;

/**
* Fit to bounds? Defaults to true.
*/
fitBounds: boolean = true;

/**
* This event emitter gets emitted when the user clicks on the marker.
*/
Expand Down Expand Up @@ -124,7 +129,7 @@ export class AgmMarker implements OnDestroy, OnChanges, AfterContentInit {
private _id: string;
private _observableSubscriptions: Subscription[] = [];

constructor(private _markerManager: MarkerManager) { this._id = (markerId++).toString(); }
constructor(private _markerManager: MarkerManager, ) { this._id = (markerId++).toString(); }

/* @internal */
ngAfterContentInit() {
Expand Down Expand Up @@ -155,6 +160,9 @@ export class AgmMarker implements OnDestroy, OnChanges, AfterContentInit {
if (changes['latitude'] || changes['longitude']) {
this._markerManager.updateMarkerPosition(this);
}
if (changes['fitBounds']) {
this._markerManager.updateBoundsOptions(this);
}
if (changes['title']) {
this._markerManager.updateTitle(this);
}
Expand Down
1 change: 1 addition & 0 deletions src/core/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export {DataLayerManager} from './services/managers/data-layer-manager';
export {GoogleMapsScriptProtocol, LAZY_MAPS_API_CONFIG, LazyMapsAPILoader, LazyMapsAPILoaderConfigLiteral} from './services/maps-api-loader/lazy-maps-api-loader';
export {MapsAPILoader} from './services/maps-api-loader/maps-api-loader';
export {NoOpMapsAPILoader} from './services/maps-api-loader/noop-maps-api-loader';
export {FitBoundsService} from './services/fitBounds.service';
58 changes: 58 additions & 0 deletions src/core/services/fitBounds.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import {MapsAPILoader} from './maps-api-loader/maps-api-loader';
import {LatLngLiteral, LatLngBounds, LatLng} from './google-maps-types';
import {Observable} from 'rxjs/Observable';
import {Injectable} from '@angular/core';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import 'rxjs/add/operator/debounce';
import 'rxjs/add/operator/skipWhile';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/observable/timer';
import 'rxjs/add/observable/fromPromise';

declare var google: any;

@Injectable()
export class FitBoundsService {
private _boundsSubject: BehaviorSubject<void> = new BehaviorSubject<void>(null);

/** @internal */
_boundsChangeDebounceTime: number = 200;

private _boundsResult: Map<any, LatLng|LatLngLiteral> = new Map();
private _boundsObservable: Observable<LatLngBounds>;

private _emitPaused: boolean = false;

constructor(loader: MapsAPILoader) {
this._boundsObservable = this._boundsSubject
.skipWhile(() => this._emitPaused)
.mergeMap(() => Observable.fromPromise(loader.load()))
.debounce(() => Observable.timer(this._boundsChangeDebounceTime))
.map(() => {
console.log('MAP');
const bounds = (new google.maps.LatLngBounds() as LatLngBounds);
this._boundsResult.forEach((b) => bounds.extend(b));
this._boundsResult.forEach((b) => console.log(b.lat, b.lng));
return bounds;
})
.distinctUntilChanged((v1: LatLngBounds, v2: LatLngBounds) => {
return v1.toString() === v2.toString();
});
}

addToBoundsResult(token: any, latLng: LatLng|LatLngLiteral): void {
this._boundsResult.set(token, latLng);
this._boundsSubject.next(null);
}

removeFromBoundsResult(token: any): void {
this._boundsResult.delete(token);
this._boundsSubject.next(null);
}

getBounds(): Observable<LatLngBounds|null> {
return this._boundsObservable;
}
}
2 changes: 1 addition & 1 deletion src/core/services/google-maps-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export interface CircleOptions {
export interface LatLngBounds {
contains(latLng: LatLng): boolean;
equals(other: LatLngBounds|LatLngBoundsLiteral): boolean;
extend(point: LatLng): void;
extend(point: LatLng|LatLngLiteral): void;
getCenter(): LatLng;
getNorthEast(): LatLng;
getSouthWest(): LatLng;
Expand Down
22 changes: 20 additions & 2 deletions src/core/services/managers/marker-manager.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { FitBoundsService } from './../fitBounds.service';
import {Injectable, NgZone} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import {Observer} from 'rxjs/Observer';
Expand All @@ -12,7 +13,10 @@ export class MarkerManager {
private _markers: Map<AgmMarker, Promise<Marker>> =
new Map<AgmMarker, Promise<Marker>>();

constructor(private _mapsWrapper: GoogleMapsAPIWrapper, private _zone: NgZone) {}
constructor(
private _mapsWrapper: GoogleMapsAPIWrapper,
private _zone: NgZone,
private _fitBoundsService: FitBoundsService) {}

deleteMarker(marker: AgmMarker): Promise<void> {
const m = this._markers.get(marker);
Expand All @@ -28,9 +32,20 @@ export class MarkerManager {
});
}

updateBoundsOptions(marker: AgmMarker): void {
if (marker.fitBounds) {
this._fitBoundsService.addToBoundsResult(this, {lat: marker.latitude, lng: marker.longitude});
} else {
this._fitBoundsService.removeFromBoundsResult(this);
}
}

updateMarkerPosition(marker: AgmMarker): Promise<void> {
return this._markers.get(marker).then(
(m: Marker) => m.setPosition({lat: marker.latitude, lng: marker.longitude}));
(m: Marker) => m.setPosition({lat: marker.latitude, lng: marker.longitude}))
.then(() => {
this.updateBoundsOptions(marker);
});
}

updateTitle(marker: AgmMarker): Promise<void> {
Expand Down Expand Up @@ -73,6 +88,9 @@ export class MarkerManager {
title: marker.title
});
this._markers.set(marker, markerPromise);
markerPromise.then(() => {
this.updateBoundsOptions(marker);
});
}

getNativeMarker(marker: AgmMarker): Promise<Marker> {
Expand Down

0 comments on commit 6ff1d85

Please sign in to comment.