-
Notifications
You must be signed in to change notification settings - Fork 817
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This introduces a new Directive called <sebm-google-map-kml-layer> Closes #734
- Loading branch information
1 parent
1e20585
commit 4d2a5d5
Showing
8 changed files
with
255 additions
and
3 deletions.
There are no files selected for viewing
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import {Directive, EventEmitter, OnChanges, OnDestroy, OnInit, SimpleChanges} from '@angular/core'; | ||
import {Subscription} from 'rxjs/Subscription'; | ||
|
||
import {KmlMouseEvent} from './../services/google-maps-types'; | ||
import {KmlLayerManager} from './../services/managers/kml-layer-manager'; | ||
|
||
let layerId = 0; | ||
|
||
@Directive({ | ||
selector: 'sebm-google-map-kml-layer', | ||
inputs: | ||
['clickable', 'preserveViewport', 'screenOverlays', 'suppressInfoWindows', 'url', 'zIndex'], | ||
outputs: ['layerClick', 'defaultViewportChange', 'statusChange'] | ||
}) | ||
export class SebmGoogleMapKmlLayer implements OnInit, OnDestroy, OnChanges { | ||
private _addedToManager: boolean = false; | ||
private _id: string = (layerId++).toString(); | ||
private _subscriptions: Subscription[] = []; | ||
private static _kmlLayerOptions: string[] = | ||
['clickable', 'preserveViewport', 'screenOverlays', 'suppressInfoWindows', 'url', 'zIndex']; | ||
|
||
/** | ||
* If true, the layer receives mouse events. Default value is true. | ||
*/ | ||
clickable: boolean = true; | ||
|
||
/** | ||
* By default, the input map is centered and zoomed to the bounding box of the contents of the | ||
* layer. | ||
* If this option is set to true, the viewport is left unchanged, unless the map's center and zoom | ||
* were never set. | ||
*/ | ||
preserveViewport: boolean = false; | ||
|
||
/** | ||
* Whether to render the screen overlays. Default true. | ||
*/ | ||
screenOverlays: boolean = true; | ||
|
||
/** | ||
* Suppress the rendering of info windows when layer features are clicked. | ||
*/ | ||
suppressInfoWindows: boolean = false; | ||
|
||
/** | ||
* The URL of the KML document to display. | ||
*/ | ||
url: string = null; | ||
|
||
/** | ||
* The z-index of the layer. | ||
*/ | ||
zIndex: number|null = null; | ||
|
||
/** | ||
* This event is fired when a feature in the layer is clicked. | ||
*/ | ||
layerClick: EventEmitter<KmlMouseEvent> = new EventEmitter<KmlMouseEvent>(); | ||
|
||
/** | ||
* This event is fired when the KML layers default viewport has changed. | ||
*/ | ||
defaultViewportChange: EventEmitter<void> = new EventEmitter<void>(); | ||
|
||
/** | ||
* This event is fired when the KML layer has finished loading. | ||
* At this point it is safe to read the status property to determine if the layer loaded | ||
* successfully. | ||
*/ | ||
statusChange: EventEmitter<void> = new EventEmitter<void>(); | ||
|
||
constructor(private _manager: KmlLayerManager) {} | ||
|
||
ngOnInit() { | ||
if (this._addedToManager) { | ||
return; | ||
} | ||
this._manager.addKmlLayer(this); | ||
this._addedToManager = true; | ||
this._addEventListeners(); | ||
} | ||
|
||
ngOnChanges(changes: SimpleChanges) { | ||
if (!this._addedToManager) { | ||
return; | ||
} | ||
this._updatePolygonOptions(changes); | ||
} | ||
|
||
private _updatePolygonOptions(changes: SimpleChanges) { | ||
const options = Object.keys(changes) | ||
.filter(k => SebmGoogleMapKmlLayer._kmlLayerOptions.indexOf(k) !== -1) | ||
.reduce((obj: any, k: string) => { | ||
obj[k] = changes[k].currentValue; | ||
return obj; | ||
}, {}); | ||
if (Object.keys(options).length > 0) { | ||
this._manager.setOptions(this, options); | ||
} | ||
} | ||
|
||
private _addEventListeners() { | ||
const listeners = [ | ||
{name: 'click', handler: (ev: KmlMouseEvent) => this.layerClick.emit(ev)}, | ||
{name: 'defaultviewport_changed', handler: () => this.defaultViewportChange.emit()}, | ||
{name: 'status_changed', handler: () => this.statusChange.emit()}, | ||
]; | ||
listeners.forEach((obj) => { | ||
const os = this._manager.createEventObservable(obj.name, this).subscribe(obj.handler); | ||
this._subscriptions.push(os); | ||
}); | ||
} | ||
|
||
/** @internal */ | ||
id(): string { return this._id; } | ||
|
||
/** @internal */ | ||
toString(): string { return `SebmGoogleMapKmlLayer-${this._id.toString()}`; } | ||
|
||
/** @internal */ | ||
ngOnDestroy() { | ||
this._manager.deleteKmlLayer(this); | ||
// unsubscribe all registered observable subscriptions | ||
this._subscriptions.forEach(s => s.unsubscribe()); | ||
} | ||
} |
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
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import {Injectable, NgZone} from '@angular/core'; | ||
import {Observable} from 'rxjs/Observable'; | ||
import {Observer} from 'rxjs/Observer'; | ||
|
||
import {SebmGoogleMapKmlLayer} from './../../directives/google-map-kml-layer'; | ||
import {GoogleMapsAPIWrapper} from './../google-maps-api-wrapper'; | ||
import {KmlLayer, KmlLayerOptions} from './../google-maps-types'; | ||
|
||
declare var google: any; | ||
|
||
/** | ||
* Manages all KML Layers for a Google Map instance. | ||
*/ | ||
@Injectable() | ||
export class KmlLayerManager { | ||
private _layers: Map<SebmGoogleMapKmlLayer, Promise<KmlLayer>> = | ||
new Map<SebmGoogleMapKmlLayer, Promise<KmlLayer>>(); | ||
|
||
constructor(private _wrapper: GoogleMapsAPIWrapper, private _zone: NgZone) {} | ||
|
||
/** | ||
* Adds a new KML Layer to the map. | ||
*/ | ||
addKmlLayer(layer: SebmGoogleMapKmlLayer) { | ||
const newLayer = this._wrapper.getNativeMap().then(m => { | ||
return new google.maps.KmlLayer(<KmlLayerOptions>{ | ||
clickable: layer.clickable, | ||
map: m, | ||
preserveViewport: layer.preserveViewport, | ||
screenOverlays: layer.screenOverlays, | ||
suppressInfoWindows: layer.suppressInfoWindows, | ||
url: layer.url, | ||
zIndex: layer.zIndex | ||
}); | ||
}); | ||
this._layers.set(layer, newLayer); | ||
} | ||
|
||
setOptions(layer: SebmGoogleMapKmlLayer, options: KmlLayerOptions) { | ||
this._layers.get(layer).then(l => l.setOptions(options)); | ||
} | ||
|
||
deleteKmlLayer(layer: SebmGoogleMapKmlLayer) { | ||
this._layers.get(layer).then(l => { | ||
l.setMap(null); | ||
this._layers.delete(layer); | ||
}); | ||
} | ||
|
||
/** | ||
* Creates a Google Maps event listener for the given KmlLayer as an Observable | ||
*/ | ||
createEventObservable<T>(eventName: string, layer: SebmGoogleMapKmlLayer): Observable<T> { | ||
return Observable.create((observer: Observer<T>) => { | ||
this._layers.get(layer).then((m: KmlLayer) => { | ||
m.addListener(eventName, (e: T) => this._zone.run(() => observer.next(e))); | ||
}); | ||
}); | ||
} | ||
} |