ng-agm-core-lib
Version:
Angular components for Google Maps
1 lines • 267 kB
Source Map (JSON)
{"version":3,"file":"ng-agm-core-lib.mjs","sources":["../../../packages/core/src/lib/services/maps-api-loader/maps-api-loader.ts","../../../packages/core/src/lib/services/google-maps-api-wrapper.ts","../../../packages/core/src/lib/services/managers/circle-manager.ts","../../../packages/core/src/lib/services/managers/data-layer-manager.ts","../../../packages/core/src/lib/services/fit-bounds.ts","../../../packages/core/src/lib/services/geocoder-service.ts","../../../packages/core/src/lib/utils/browser-globals.ts","../../../packages/core/src/lib/services/maps-api-loader/lazy-maps-api-loader.ts","../../../packages/core/src/lib/services/managers/marker-manager.ts","../../../packages/core/src/lib/services/managers/info-window-manager.ts","../../../packages/core/src/lib/services/managers/kml-layer-manager.ts","../../../packages/core/src/lib/services/managers/layer-manager.ts","../../../packages/core/src/lib/services/maps-api-loader/noop-maps-api-loader.ts","../../../packages/core/src/lib/utils/mvcarray-utils.ts","../../../packages/core/src/lib/services/managers/polygon-manager.ts","../../../packages/core/src/lib/services/managers/polyline-manager.ts","../../../packages/core/src/lib/services/managers/rectangle-manager.ts","../../../packages/core/src/lib/directives/bicycling-layer.ts","../../../packages/core/src/lib/directives/circle.ts","../../../packages/core/src/lib/directives/data-layer.ts","../../../packages/core/src/lib/directives/fit-bounds.ts","../../../packages/core/src/lib/directives/info-window.ts","../../../packages/core/src/lib/directives/kml-layer.ts","../../../packages/core/src/lib/directives/map.ts","../../../packages/core/src/lib/directives/marker.ts","../../../packages/core/src/lib/directives/polygon.ts","../../../packages/core/src/lib/directives/polyline-icon.ts","../../../packages/core/src/lib/directives/polyline-point.ts","../../../packages/core/src/lib/directives/polyline.ts","../../../packages/core/src/lib/directives/rectangle.ts","../../../packages/core/src/lib/directives/transit-layer.ts","../../../packages/core/src/lib/core.module.ts","../../../packages/core/src/public-api.ts","../../../packages/core/src/ng-agm-core-lib.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\n\n@Injectable()\nexport abstract class MapsAPILoader {\n abstract load(): Promise<void>;\n}\n","import { Injectable, NgZone } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { MapsAPILoader } from './maps-api-loader/maps-api-loader';\n\n/**\n * Wrapper class that handles the communication with the Google Maps Javascript\n * API v3\n */\n@Injectable()\nexport class GoogleMapsAPIWrapper {\n private _map: Promise<google.maps.Map>;\n private _mapResolver: (value?: google.maps.Map) => void;\n\n constructor(private _loader: MapsAPILoader, private _zone: NgZone) {\n this._map =\n new Promise<google.maps.Map>((resolve: (value: google.maps.Map) => void) => { this._mapResolver = resolve; });\n }\n\n createMap(el: HTMLElement, mapOptions: google.maps.MapOptions): Promise<void> {\n return this._zone.runOutsideAngular(() => {\n return this._loader.load().then(() => {\n const map = new google.maps.Map(el, mapOptions);\n this._mapResolver(map);\n return;\n });\n });\n }\n\n setMapOptions(options: google.maps.MapOptions) {\n return this._zone.runOutsideAngular(() => {\n this._map.then((m: google.maps.Map) => { m.setOptions(options); });\n });\n }\n\n /**\n * Creates a google map marker with the map context\n */\n createMarker(options: google.maps.MarkerOptions = {}, addToMap: boolean = true):\n Promise<google.maps.Marker> {\n return this._zone.runOutsideAngular(() => {\n return this._map.then((map: google.maps.Map) => {\n if (addToMap) {\n options.map = map;\n }\n return new google.maps.Marker(options);\n });\n });\n }\n\n createInfoWindow(options?: google.maps.InfoWindowOptions): Promise<google.maps.InfoWindow> {\n return this._zone.runOutsideAngular(() => {\n return this._map.then(() => new google.maps.InfoWindow(options));\n });\n }\n\n /**\n * Creates a google.map.Circle for the current map.\n */\n createCircle(options: google.maps.CircleOptions): Promise<google.maps.Circle> {\n return this._zone.runOutsideAngular(() => {\n return this._map.then((map: google.maps.Map) => {\n options.map = map;\n return new google.maps.Circle(options);\n });\n });\n }\n\n /**\n * Creates a google.map.Rectangle for the current map.\n */\n createRectangle(options: google.maps.RectangleOptions): Promise<google.maps.Rectangle> {\n return this._zone.runOutsideAngular(() => {\n return this._map.then((map: google.maps.Map) => {\n options.map = map;\n return new google.maps.Rectangle(options);\n });\n });\n }\n\n createPolyline(options: google.maps.PolylineOptions): Promise<google.maps.Polyline> {\n return this._zone.runOutsideAngular(() => {\n return this.getNativeMap().then((map: google.maps.Map) => {\n const line = new google.maps.Polyline(options);\n line.setMap(map);\n return line;\n });\n });\n }\n\n createPolygon(options: google.maps.PolygonOptions): Promise<google.maps.Polygon> {\n return this._zone.runOutsideAngular(() => {\n return this.getNativeMap().then((map: google.maps.Map) => {\n const polygon = new google.maps.Polygon(options);\n polygon.setMap(map);\n return polygon;\n });\n });\n }\n\n /**\n * Creates a new google.map.Data layer for the current map\n */\n createDataLayer(options?: google.maps.Data.DataOptions): Promise<google.maps.Data> {\n return this._zone.runOutsideAngular(() => {\n return this._map.then(m => {\n const data = new google.maps.Data(options);\n data.setMap(m);\n return data;\n });\n });\n }\n\n /**\n * Creates a TransitLayer instance for a map\n * @returns a new transit layer object\n */\n createTransitLayer(): Promise<google.maps.TransitLayer>{\n return this._zone.runOutsideAngular(() => {\n return this._map.then((map: google.maps.Map) => {\n const newLayer: google.maps.TransitLayer = new google.maps.TransitLayer();\n newLayer.setMap(map);\n return newLayer;\n });\n });\n }\n\n /**\n * Creates a BicyclingLayer instance for a map\n * @returns a new bicycling layer object\n */\n createBicyclingLayer(): Promise<google.maps.BicyclingLayer>{\n return this._zone.runOutsideAngular(() => {\n return this._map.then((map: google.maps.Map) => {\n const newLayer: google.maps.BicyclingLayer = new google.maps.BicyclingLayer();\n newLayer.setMap(map);\n return newLayer;\n });\n });\n }\n\n /**\n * Determines if given coordinates are insite a Polygon path.\n */\n containsLocation(latLng: google.maps.LatLng, polygon: google.maps.Polygon): Promise<boolean> {\n return this._map.then(() => google.maps.geometry.poly.containsLocation(latLng, polygon));\n }\n\n subscribeToMapEvent<N extends keyof google.maps.MapHandlerMap>(eventName: N)\n : Observable<google.maps.MapHandlerMap[N]> {\n return new Observable((observer) => {\n this._map.then(m =>\n m.addListener(eventName, (...evArgs) => this._zone.run(() => observer.next(evArgs)))\n );\n });\n }\n\n clearInstanceListeners() {\n return this._zone.runOutsideAngular(() => {\n this._map.then((map: google.maps.Map) => {\n google.maps.event.clearInstanceListeners(map);\n });\n });\n }\n\n setCenter(latLng: google.maps.LatLngLiteral): Promise<void> {\n return this._zone.runOutsideAngular(() => {\n return this._map.then((map: google.maps.Map) => map.setCenter(latLng));\n });\n }\n\n getZoom(): Promise<number> {\n return this._zone.runOutsideAngular(() => {\n return this._map.then((map: google.maps.Map) => map.getZoom());\n });\n }\n\n getBounds(): Promise<google.maps.LatLngBounds> {\n return this._zone.runOutsideAngular(() => {\n return this._map.then((map: google.maps.Map) => map.getBounds());\n });\n }\n\n getMapTypeId(): Promise<google.maps.MapTypeId> {\n return this._zone.runOutsideAngular(() => {\n return this._map.then((map: google.maps.Map) => map.getMapTypeId());\n });\n }\n\n setZoom(zoom: number): Promise<void> {\n return this._zone.runOutsideAngular(() => {\n return this._map.then((map: google.maps.Map) => map.setZoom(zoom));\n });\n }\n\n getCenter(): Promise<google.maps.LatLng> {\n return this._zone.runOutsideAngular(() => {\n return this._map.then((map: google.maps.Map) => map.getCenter());\n });\n }\n\n panTo(latLng: google.maps.LatLng | google.maps.LatLngLiteral): Promise<void> {\n return this._zone.runOutsideAngular(() => {\n return this._map.then((map) => map.panTo(latLng));\n });\n }\n\n panBy(x: number, y: number): Promise<void> {\n return this._zone.runOutsideAngular(() => {\n return this._map.then((map) => map.panBy(x, y));\n });\n }\n\n fitBounds(latLng: google.maps.LatLngBounds | google.maps.LatLngBoundsLiteral, padding?: number | google.maps.Padding): Promise<void> {\n return this._zone.runOutsideAngular(() => {\n return this._map.then((map) => map.fitBounds(latLng, padding));\n });\n }\n\n panToBounds(latLng: google.maps.LatLngBounds | google.maps.LatLngBoundsLiteral, padding?: number | google.maps.Padding): Promise<void> {\n return this._zone.runOutsideAngular(() => {\n return this._map.then((map) => map.panToBounds(latLng, padding));\n });\n }\n\n /**\n * Returns the native Google Maps Map instance. Be careful when using this instance directly.\n */\n getNativeMap(): Promise<google.maps.Map> { return this._map; }\n\n /**\n * Triggers the given event name on the map instance.\n */\n triggerMapEvent(eventName: string): Promise<void> {\n return this._map.then((m) => google.maps.event.trigger(m, eventName));\n }\n}\n","import { Injectable, NgZone } from '@angular/core';\n\nimport { Observable, Observer } from 'rxjs';\n\nimport { AgmCircle } from '../../directives/circle';\nimport { GoogleMapsAPIWrapper } from '../google-maps-api-wrapper';\n\n@Injectable()\nexport class CircleManager {\n private _circles: Map<AgmCircle, Promise<google.maps.Circle>> =\n new Map<AgmCircle, Promise<google.maps.Circle>>();\n\n constructor(private _apiWrapper: GoogleMapsAPIWrapper, private _zone: NgZone) {}\n\n addCircle(circle: AgmCircle) {\n this._circles.set(circle, this._apiWrapper.getNativeMap().then( () =>\n this._apiWrapper.createCircle({\n center: {lat: circle.latitude, lng: circle.longitude},\n clickable: circle.clickable,\n draggable: circle.draggable,\n editable: circle.editable,\n fillColor: circle.fillColor,\n fillOpacity: circle.fillOpacity,\n radius: circle.radius,\n strokeColor: circle.strokeColor,\n strokeOpacity: circle.strokeOpacity,\n strokePosition: google.maps.StrokePosition[circle.strokePosition],\n strokeWeight: circle.strokeWeight,\n visible: circle.visible,\n zIndex: circle.zIndex,\n }))\n );\n }\n\n /**\n * Removes the given circle from the map.\n */\n removeCircle(circle: AgmCircle): Promise<void> {\n return this._circles.get(circle).then((c) => {\n c.setMap(null);\n this._circles.delete(circle);\n });\n }\n\n async setOptions(circle: AgmCircle, options: google.maps.CircleOptions) {\n return this._circles.get(circle).then((c) => {\n const actualParam = options.strokePosition as any as keyof typeof google.maps.StrokePosition;\n options.strokePosition = google.maps.StrokePosition[actualParam];\n c.setOptions(options);\n });\n }\n\n getBounds(circle: AgmCircle): Promise<google.maps.LatLngBounds> {\n return this._circles.get(circle).then((c) => c.getBounds());\n }\n\n getCenter(circle: AgmCircle): Promise<google.maps.LatLng> {\n return this._circles.get(circle).then((c) => c.getCenter());\n }\n\n getRadius(circle: AgmCircle): Promise<number> {\n return this._circles.get(circle).then((c) => c.getRadius());\n }\n\n setCenter(circle: AgmCircle): Promise<void> {\n return this._circles.get(circle).then(\n c => c.setCenter({lat: circle.latitude, lng: circle.longitude}));\n }\n\n setEditable(circle: AgmCircle): Promise<void> {\n return this._circles.get(circle).then(c => c.setEditable(circle.editable));\n }\n\n setDraggable(circle: AgmCircle): Promise<void> {\n return this._circles.get(circle).then(c => c.setDraggable(circle.draggable));\n }\n\n setVisible(circle: AgmCircle): Promise<void> {\n return this._circles.get(circle).then(c => c.setVisible(circle.visible));\n }\n\n setRadius(circle: AgmCircle): Promise<void> {\n return this._circles.get(circle).then(c => c.setRadius(circle.radius));\n }\n\n getNativeCircle(circle: AgmCircle): Promise<google.maps.Circle> {\n return this._circles.get(circle);\n }\n\n createEventObservable<T>(eventName: string, circle: AgmCircle): Observable<T> {\n return new Observable((observer: Observer<T>) => {\n let listener: google.maps.MapsEventListener = null;\n this._circles.get(circle).then((c) => {\n listener = c.addListener(eventName, (e: T) => this._zone.run(() => observer.next(e)));\n });\n\n return () => {\n if (listener !== null) {\n listener.remove();\n }\n };\n });\n }\n}\n","import { Injectable, NgZone } from '@angular/core';\nimport { Observable, Observer } from 'rxjs';\n\nimport { AgmDataLayer } from './../../directives/data-layer';\nimport { GoogleMapsAPIWrapper } from './../google-maps-api-wrapper';\n\n/**\n * Manages all Data Layers for a Google Map instance.\n */\n@Injectable()\nexport class DataLayerManager {\n private _layers: Map<AgmDataLayer, Promise<google.maps.Data>> =\n new Map<AgmDataLayer, Promise<google.maps.Data>>();\n\n constructor(private _wrapper: GoogleMapsAPIWrapper, private _zone: NgZone) { }\n\n /**\n * Adds a new Data Layer to the map.\n */\n addDataLayer(layer: AgmDataLayer) {\n const newLayer = this._wrapper.createDataLayer({\n style: layer.style,\n } as google.maps.Data.DataOptions)\n .then(d => {\n if (layer.geoJson) {\n // NOTE: accessing \"features\" on google.maps.Data is undocumented\n this.getDataFeatures(d, layer.geoJson).then(features => (d as any).features = features);\n }\n return d;\n });\n this._layers.set(layer, newLayer);\n }\n\n deleteDataLayer(layer: AgmDataLayer) {\n this._layers.get(layer).then(l => {\n l.setMap(null);\n this._layers.delete(layer);\n });\n }\n\n updateGeoJson(layer: AgmDataLayer, geoJson: object | string) {\n this._layers.get(layer).then(l => {\n l.forEach(feature => {\n l.remove(feature);\n\n // NOTE: accessing \"features\" on google.maps.Data is undocumented\n const index = (l as any).features.indexOf(feature, 0);\n if (index > -1) {\n (l as any).features.splice(index, 1);\n }\n });\n this.getDataFeatures(l, geoJson).then(features => (l as any).features = features);\n });\n }\n\n setDataOptions(layer: AgmDataLayer, options: google.maps.Data.DataOptions)\n {\n this._layers.get(layer).then(l => {\n l.setControlPosition(options.controlPosition);\n l.setControls(options.controls);\n l.setDrawingMode(options.drawingMode);\n l.setStyle(options.style);\n });\n }\n\n /**\n * Creates a Google Maps event listener for the given DataLayer as an Observable\n */\n createEventObservable<T>(eventName: string, layer: AgmDataLayer): Observable<T> {\n return new Observable((observer: Observer<T>) => {\n this._layers.get(layer).then((d: google.maps.Data) => {\n d.addListener(eventName, (e: T) => this._zone.run(() => observer.next(e)));\n });\n });\n }\n\n /**\n * Extract features from a geoJson using google.maps Data Class\n * @param d : google.maps.Data class instance\n * @param geoJson : url or geojson object\n */\n getDataFeatures(d: google.maps.Data, geoJson: object | string): Promise<google.maps.Data.Feature[]> {\n return new Promise<google.maps.Data.Feature[]>((resolve, reject) => {\n if (typeof geoJson === 'object') {\n try {\n const features = d.addGeoJson(geoJson);\n resolve(features);\n } catch (e) {\n reject(e);\n }\n } else if (typeof geoJson === 'string') {\n d.loadGeoJson(geoJson, null, resolve);\n } else {\n reject(`Impossible to extract features from geoJson: wrong argument type`);\n }\n });\n }\n}\n","import { Injectable } from '@angular/core';\nimport { BehaviorSubject, from, Observable, timer } from 'rxjs';\nimport {\n flatMap,\n map,\n sample,\n shareReplay,\n switchMap,\n} from 'rxjs/operators';\nimport { MapsAPILoader } from './maps-api-loader/maps-api-loader';\n\nexport interface FitBoundsDetails {\n latLng: google.maps.LatLng | google.maps.LatLngLiteral;\n}\n\n/**\n * @internal\n */\nexport type BoundsMap = Map<string, google.maps.LatLng | google.maps.LatLngLiteral>;\n\n/**\n * Class to implement when you what to be able to make it work with the auto fit bounds feature\n * of AGM.\n */\nexport abstract class FitBoundsAccessor {\n abstract getFitBoundsDetails$(): Observable<FitBoundsDetails>;\n}\n\n/**\n * The FitBoundsService is responsible for computing the bounds of the a single map.\n */\n@Injectable()\nexport class FitBoundsService {\n protected readonly bounds$: Observable<google.maps.LatLngBounds>;\n protected readonly _boundsChangeSampleTime$ = new BehaviorSubject<number>(200);\n protected readonly _includeInBounds$ = new BehaviorSubject<BoundsMap>(new Map<string, google.maps.LatLng | google.maps.LatLngLiteral>());\n\n constructor(loader: MapsAPILoader) {\n this.bounds$ = from(loader.load()).pipe(\n flatMap(() => this._includeInBounds$),\n sample(\n this._boundsChangeSampleTime$.pipe(switchMap(time => timer(0, time))),\n ),\n map(includeInBounds => this._generateBounds(includeInBounds)),\n shareReplay(1),\n );\n }\n\n private _generateBounds(\n includeInBounds: Map<string, google.maps.LatLng | google.maps.LatLngLiteral>\n ) {\n const bounds = new google.maps.LatLngBounds();\n includeInBounds.forEach(b => bounds.extend(b));\n return bounds;\n }\n\n addToBounds(latLng: google.maps.LatLng | google.maps.LatLngLiteral) {\n const id = this._createIdentifier(latLng);\n if (this._includeInBounds$.value.has(id)) {\n return;\n }\n const boundsMap = this._includeInBounds$.value;\n boundsMap.set(id, latLng);\n this._includeInBounds$.next(boundsMap);\n }\n\n removeFromBounds(latLng: google.maps.LatLng | google.maps.LatLngLiteral) {\n const boundsMap = this._includeInBounds$.value;\n boundsMap.delete(this._createIdentifier(latLng));\n this._includeInBounds$.next(boundsMap);\n }\n\n changeFitBoundsChangeSampleTime(timeMs: number) {\n this._boundsChangeSampleTime$.next(timeMs);\n }\n\n getBounds$(): Observable<google.maps.LatLngBounds> {\n return this.bounds$;\n }\n\n protected _createIdentifier(latLng: google.maps.LatLng | google.maps.LatLngLiteral): string {\n return `${latLng.lat}+${latLng.lng}`;\n }\n}\n","import { Injectable } from '@angular/core';\nimport { bindCallback, ConnectableObservable, Observable, of, ReplaySubject, throwError } from 'rxjs';\nimport { map, multicast, switchMap } from 'rxjs/operators';\nimport { MapsAPILoader } from './maps-api-loader/maps-api-loader';\n\n@Injectable({ providedIn: 'root' })\nexport class AgmGeocoder {\n protected readonly geocoder$: Observable<google.maps.Geocoder>;\n\n constructor(loader: MapsAPILoader) {\n const connectableGeocoder$ = new Observable(subscriber => {\n loader.load().then(() => subscriber.next());\n })\n .pipe(\n map(() => this._createGeocoder()),\n multicast(new ReplaySubject(1)),\n ) as ConnectableObservable<google.maps.Geocoder>;\n\n connectableGeocoder$.connect(); // ignore the subscription\n // since we will remain subscribed till application exits\n\n this.geocoder$ = connectableGeocoder$;\n }\n\n geocode(request: google.maps.GeocoderRequest): Observable<google.maps.GeocoderResult[]> {\n return this.geocoder$.pipe(\n switchMap((geocoder) => this._getGoogleResults(geocoder, request))\n );\n }\n\n private _getGoogleResults(geocoder: google.maps.Geocoder, request: google.maps.GeocoderRequest):\n Observable<google.maps.GeocoderResult[]> {\n const geocodeObservable = bindCallback(geocoder.geocode);\n return geocodeObservable(request).pipe(\n switchMap(([results, status]) => {\n if (status === google.maps.GeocoderStatus.OK) {\n return of(results);\n }\n\n return throwError(status);\n })\n );\n }\n\n private _createGeocoder() {\n return new google.maps.Geocoder();\n }\n}\n","import { Provider } from '@angular/core';\n\nexport class WindowRef {\n getNativeWindow(): any { return window; }\n}\n\nexport class DocumentRef {\n getNativeDocument(): any { return document; }\n}\n\nexport const BROWSER_GLOBALS_PROVIDERS: Provider[] = [WindowRef, DocumentRef];\n","import { Inject, Injectable, InjectionToken, LOCALE_ID, Optional } from '@angular/core';\n\nimport { DocumentRef, WindowRef } from '../../utils/browser-globals';\n\nimport { MapsAPILoader } from './maps-api-loader';\n\nexport enum GoogleMapsScriptProtocol {\n HTTP = 1,\n HTTPS = 2,\n AUTO = 3,\n}\n\n/**\n * Token for the config of the LazyMapsAPILoader. Please provide an object of type {@link\n * LazyMapsAPILoaderConfig}.\n */\nexport const LAZY_MAPS_API_CONFIG = new InjectionToken<LazyMapsAPILoaderConfigLiteral>('angular-google-maps LAZY_MAPS_API_CONFIG');\n\n/**\n * Configuration for the {@link LazyMapsAPILoader}.\n */\nexport interface LazyMapsAPILoaderConfigLiteral {\n /**\n * The Google Maps API Key (see:\n * https://developers.google.com/maps/documentation/javascript/get-api-key)\n */\n apiKey?: string;\n\n /**\n * The Google Maps client ID (for premium plans).\n * When you have a Google Maps APIs Premium Plan license, you must authenticate\n * your application with either an API key or a client ID.\n * The Google Maps API will fail to load if both a client ID and an API key are included.\n */\n clientId?: string;\n\n /**\n * The Google Maps channel name (for premium plans).\n * A channel parameter is an optional parameter that allows you to track usage under your client\n * ID by assigning a distinct channel to each of your applications.\n */\n channel?: string;\n\n /**\n * Google Maps API version.\n */\n apiVersion?: string;\n\n /**\n * Host and Path used for the `<script>` tag.\n */\n hostAndPath?: string;\n\n /**\n * Protocol used for the `<script>` tag.\n */\n protocol?: GoogleMapsScriptProtocol;\n\n /**\n * Defines which Google Maps libraries should get loaded.\n */\n libraries?: string[];\n\n /**\n * The default bias for the map behavior is US.\n * If you wish to alter your application to serve different map tiles or bias the\n * application, you can overwrite the default behavior (US) by defining a `region`.\n * See https://developers.google.com/maps/documentation/javascript/basics#Region\n */\n region?: string;\n\n /**\n * The Google Maps API uses the browser's preferred language when displaying\n * textual information. If you wish to overwrite this behavior and force the API\n * to use a given language, you can use this setting.\n * See https://developers.google.com/maps/documentation/javascript/basics#Language\n */\n language?: string;\n}\n\n@Injectable()\nexport class LazyMapsAPILoader extends MapsAPILoader {\n protected _scriptLoadingPromise: Promise<void>;\n protected _config: LazyMapsAPILoaderConfigLiteral;\n protected _windowRef: WindowRef;\n protected _documentRef: DocumentRef;\n protected readonly _SCRIPT_ID: string = 'agmGoogleMapsApiScript';\n protected readonly callbackName: string = `agmLazyMapsAPILoader`;\n\n constructor(@Optional() @Inject(LAZY_MAPS_API_CONFIG) config: any = null, w: WindowRef, d: DocumentRef,\n @Inject(LOCALE_ID) private localeId: string) {\n super();\n this._config = config || {};\n this._windowRef = w;\n this._documentRef = d;\n }\n\n load(): Promise<void> {\n const window = this._windowRef.getNativeWindow() as any;\n if (window.google && window.google.maps) {\n // Google maps already loaded on the page.\n return Promise.resolve();\n }\n\n if (this._scriptLoadingPromise) {\n return this._scriptLoadingPromise;\n }\n\n // this can happen in HMR situations or Stackblitz.io editors.\n const scriptOnPage = this._documentRef.getNativeDocument().getElementById(this._SCRIPT_ID);\n if (scriptOnPage) {\n this._assignScriptLoadingPromise(scriptOnPage);\n return this._scriptLoadingPromise;\n }\n\n const script = this._documentRef.getNativeDocument().createElement('script');\n script.type = 'text/javascript';\n script.async = true;\n script.defer = true;\n script.id = this._SCRIPT_ID;\n script.src = this._getScriptSrc(this.callbackName);\n this._assignScriptLoadingPromise(script);\n this._documentRef.getNativeDocument().body.appendChild(script);\n return this._scriptLoadingPromise;\n }\n\n private _assignScriptLoadingPromise(scriptElem: HTMLElement) {\n this._scriptLoadingPromise = new Promise((resolve, reject) => {\n this._windowRef.getNativeWindow()[this.callbackName] = () => {\n resolve();\n };\n\n scriptElem.onerror = (error: Event) => {\n reject(error);\n };\n });\n }\n\n protected _getScriptSrc(callbackName: string): string {\n const protocolType: GoogleMapsScriptProtocol =\n (this._config && this._config.protocol) || GoogleMapsScriptProtocol.HTTPS;\n let protocol: string;\n\n switch (protocolType) {\n case GoogleMapsScriptProtocol.AUTO:\n protocol = '';\n break;\n case GoogleMapsScriptProtocol.HTTP:\n protocol = 'http:';\n break;\n case GoogleMapsScriptProtocol.HTTPS:\n protocol = 'https:';\n break;\n }\n\n const hostAndPath: string = this._config.hostAndPath || 'maps.googleapis.com/maps/api/js';\n const queryParams: {[key: string]: string | string[]} = {\n v: this._config.apiVersion || 'quarterly',\n callback: callbackName,\n key: this._config.apiKey,\n client: this._config.clientId,\n channel: this._config.channel,\n libraries: this._config.libraries,\n region: this._config.region,\n language: this._config.language || (this.localeId !== 'en-US' ? this.localeId : null),\n };\n const params: string = Object.keys(queryParams)\n .filter((k: string) => queryParams[k] != null)\n .filter((k: string) => {\n // remove empty arrays\n return !Array.isArray(queryParams[k]) ||\n (Array.isArray(queryParams[k]) && queryParams[k].length > 0);\n })\n .map((k: string) => {\n // join arrays as comma seperated strings\n const i = queryParams[k];\n if (Array.isArray(i)) {\n return {key: k, value: i.join(',')};\n }\n return {key: k, value: queryParams[k]};\n })\n .map((entry: {key: string, value: string}) => {\n return `${entry.key}=${entry.value}`;\n })\n .join('&');\n return `${protocol}//${hostAndPath}?${params}`;\n }\n}\n","import { Injectable, NgZone } from '@angular/core';\nimport { Observable } from 'rxjs';\n\nimport { AgmMarker } from './../../directives/marker';\n\nimport { GoogleMapsAPIWrapper } from './../google-maps-api-wrapper';\n\n@Injectable()\nexport class MarkerManager {\n protected _markers: Map<AgmMarker, Promise<google.maps.Marker>> =\n new Map<AgmMarker, Promise<google.maps.Marker>>();\n\n constructor(protected _mapsWrapper: GoogleMapsAPIWrapper, protected _zone: NgZone) {}\n\n async convertAnimation(uiAnim: keyof typeof google.maps.Animation | null) {\n if (uiAnim === null) {\n return null;\n } else {\n return this._mapsWrapper.getNativeMap().then(() => google.maps.Animation[uiAnim]);\n }\n }\n\n deleteMarker(markerDirective: AgmMarker): Promise<void> {\n const markerPromise = this._markers.get(markerDirective);\n if (markerPromise == null) {\n // marker already deleted\n return Promise.resolve();\n }\n return markerPromise.then((marker: google.maps.Marker) => {\n return this._zone.run(() => {\n marker.setMap(null);\n this._markers.delete(markerDirective);\n });\n });\n }\n\n updateMarkerPosition(marker: AgmMarker): Promise<void> {\n return this._markers.get(marker).then(\n (m: google.maps.Marker) => m.setPosition({lat: marker.latitude, lng: marker.longitude}));\n }\n\n updateTitle(marker: AgmMarker): Promise<void> {\n return this._markers.get(marker).then((m: google.maps.Marker) => m.setTitle(marker.title));\n }\n\n updateLabel(marker: AgmMarker): Promise<void> {\n return this._markers.get(marker).then((m: google.maps.Marker) => { m.setLabel(marker.label); });\n }\n\n updateDraggable(marker: AgmMarker): Promise<void> {\n return this._markers.get(marker).then((m: google.maps.Marker) => m.setDraggable(marker.draggable));\n }\n\n updateIcon(marker: AgmMarker): Promise<void> {\n return this._markers.get(marker).then((m: google.maps.Marker) => m.setIcon(marker.iconUrl));\n }\n\n updateOpacity(marker: AgmMarker): Promise<void> {\n return this._markers.get(marker).then((m: google.maps.Marker) => m.setOpacity(marker.opacity));\n }\n\n updateVisible(marker: AgmMarker): Promise<void> {\n return this._markers.get(marker).then((m: google.maps.Marker) => m.setVisible(marker.visible));\n }\n\n updateZIndex(marker: AgmMarker): Promise<void> {\n return this._markers.get(marker).then((m: google.maps.Marker) => m.setZIndex(marker.zIndex));\n }\n\n updateClickable(marker: AgmMarker): Promise<void> {\n return this._markers.get(marker).then((m: google.maps.Marker) => m.setClickable(marker.clickable));\n }\n\n async updateAnimation(marker: AgmMarker) {\n const m = await this._markers.get(marker);\n m.setAnimation(await this.convertAnimation(marker.animation));\n }\n\n addMarker(marker: AgmMarker) {\n const markerPromise = new Promise<google.maps.Marker>(async (resolve) =>\n this._mapsWrapper.createMarker({\n position: {lat: marker.latitude, lng: marker.longitude},\n label: marker.label,\n draggable: marker.draggable,\n icon: marker.iconUrl,\n opacity: marker.opacity,\n visible: marker.visible,\n zIndex: marker.zIndex,\n title: marker.title,\n clickable: marker.clickable,\n animation: await this.convertAnimation(marker.animation),\n }).then(resolve));\n this._markers.set(marker, markerPromise);\n }\n\n getNativeMarker(marker: AgmMarker): Promise<google.maps.Marker> {\n return this._markers.get(marker);\n }\n\n createEventObservable<T extends (google.maps.MouseEvent | void)>(\n eventName: google.maps.MarkerMouseEventNames | google.maps.MarkerChangeOptionEventNames,\n marker: AgmMarker): Observable<T> {\n return new Observable(observer => {\n this._markers.get(marker).then(m =>\n m.addListener(eventName, e => this._zone.run(() => observer.next(e)))\n );\n });\n }\n}\n","import { Injectable, NgZone } from '@angular/core';\nimport { Observable, Observer } from 'rxjs';\n\nimport { AgmInfoWindow } from '../../directives/info-window';\n\nimport { GoogleMapsAPIWrapper } from '../google-maps-api-wrapper';\nimport { MarkerManager } from './marker-manager';\n\n@Injectable()\nexport class InfoWindowManager {\n private _infoWindows: Map<AgmInfoWindow, Promise<google.maps.InfoWindow>> =\n new Map<AgmInfoWindow, Promise<google.maps.InfoWindow>>();\n\n constructor(\n private _mapsWrapper: GoogleMapsAPIWrapper, private _zone: NgZone,\n private _markerManager: MarkerManager) {}\n\n deleteInfoWindow(infoWindow: AgmInfoWindow): Promise<void> {\n const iWindow = this._infoWindows.get(infoWindow);\n if (iWindow == null) {\n // info window already deleted\n return Promise.resolve();\n }\n return iWindow.then((i: google.maps.InfoWindow) => {\n return this._zone.run(() => {\n i.close();\n this._infoWindows.delete(infoWindow);\n });\n });\n }\n\n setPosition(infoWindow: AgmInfoWindow): Promise<void> {\n return this._infoWindows.get(infoWindow).then((i: google.maps.InfoWindow) => i.setPosition({\n lat: infoWindow.latitude,\n lng: infoWindow.longitude,\n }));\n }\n\n setZIndex(infoWindow: AgmInfoWindow): Promise<void> {\n return this._infoWindows.get(infoWindow)\n .then((i: google.maps.InfoWindow) => i.setZIndex(infoWindow.zIndex));\n }\n\n open(infoWindow: AgmInfoWindow): Promise<void> {\n return this._infoWindows.get(infoWindow).then((w) => {\n if (infoWindow.hostMarker != null) {\n return this._markerManager.getNativeMarker(infoWindow.hostMarker).then((marker) => {\n return this._mapsWrapper.getNativeMap().then((map) => w.open(map, marker));\n });\n }\n return this._mapsWrapper.getNativeMap().then((map) => w.open(map));\n });\n }\n\n close(infoWindow: AgmInfoWindow): Promise<void> {\n return this._infoWindows.get(infoWindow).then((w) => w.close());\n }\n\n setOptions(infoWindow: AgmInfoWindow, options: google.maps.InfoWindowOptions) {\n return this._infoWindows.get(infoWindow).then((i: google.maps.InfoWindow) => i.setOptions(options));\n }\n\n addInfoWindow(infoWindow: AgmInfoWindow) {\n const options: google.maps.InfoWindowOptions = {\n content: infoWindow.content,\n maxWidth: infoWindow.maxWidth,\n zIndex: infoWindow.zIndex,\n disableAutoPan: infoWindow.disableAutoPan,\n };\n if (typeof infoWindow.latitude === 'number' && typeof infoWindow.longitude === 'number') {\n options.position = {lat: infoWindow.latitude, lng: infoWindow.longitude};\n }\n const infoWindowPromise = this._mapsWrapper.createInfoWindow(options);\n this._infoWindows.set(infoWindow, infoWindowPromise);\n }\n\n /**\n * Creates a Google Maps event listener for the given InfoWindow as an Observable\n */\n createEventObservable<T>(eventName: string, infoWindow: AgmInfoWindow): Observable<T> {\n return new Observable((observer: Observer<T>) => {\n this._infoWindows.get(infoWindow).then((i: google.maps.InfoWindow) => {\n i.addListener(eventName, (e: T) => this._zone.run(() => observer.next(e)));\n });\n });\n }\n}\n","import { Injectable, NgZone } from '@angular/core';\nimport { Observable, Observer } from 'rxjs';\n\nimport { AgmKmlLayer } from './../../directives/kml-layer';\nimport { GoogleMapsAPIWrapper } from './../google-maps-api-wrapper';\n\n/**\n * Manages all KML Layers for a Google Map instance.\n */\n@Injectable()\nexport class KmlLayerManager {\n private _layers: Map<AgmKmlLayer, Promise<google.maps.KmlLayer>> =\n new Map<AgmKmlLayer, Promise<google.maps.KmlLayer>>();\n\n constructor(private _wrapper: GoogleMapsAPIWrapper, private _zone: NgZone) {}\n\n /**\n * Adds a new KML Layer to the map.\n */\n addKmlLayer(layer: AgmKmlLayer) {\n const newLayer = this._wrapper.getNativeMap().then(m => {\n return new google.maps.KmlLayer({\n clickable: layer.clickable,\n map: m,\n preserveViewport: layer.preserveViewport,\n screenOverlays: layer.screenOverlays,\n suppressInfoWindows: layer.suppressInfoWindows,\n url: layer.url,\n zIndex: layer.zIndex,\n });\n });\n this._layers.set(layer, newLayer);\n }\n\n setOptions(layer: AgmKmlLayer, options: google.maps.KmlLayerOptions) {\n this._layers.get(layer).then(l => l.setOptions(options));\n }\n\n deleteKmlLayer(layer: AgmKmlLayer) {\n this._layers.get(layer).then(l => {\n l.setMap(null);\n this._layers.delete(layer);\n });\n }\n\n /**\n * Creates a Google Maps event listener for the given KmlLayer as an Observable\n */\n createEventObservable<T>(eventName: string, layer: AgmKmlLayer): Observable<T> {\n return new Observable((observer: Observer<T>) => {\n this._layers.get(layer).then((m: google.maps.KmlLayer) => {\n m.addListener(eventName, (e: T) => this._zone.run(() => observer.next(e)));\n });\n });\n }\n}\n","import { Injectable } from '@angular/core';\nimport { AgmBicyclingLayer } from '../../directives/bicycling-layer';\nimport { AgmTransitLayer } from '../../directives/transit-layer';\nimport { GoogleMapsAPIWrapper } from '../google-maps-api-wrapper';\n\n/**\n * This class manages Transit and Bicycling Layers for a Google Map instance.\n */\n\n@Injectable()\nexport class LayerManager {\n private _layers: Map<AgmTransitLayer | AgmBicyclingLayer, Promise<google.maps.TransitLayer | google.maps.BicyclingLayer>> =\n new Map<AgmTransitLayer | AgmBicyclingLayer, Promise<google.maps.TransitLayer | google.maps.BicyclingLayer>>();\n\n constructor(private _wrapper: GoogleMapsAPIWrapper) {}\n\n /**\n * Adds a transit layer to a map instance.\n * @param layer - a TransitLayer object\n * @param _options - TransitLayerOptions options\n * @returns void\n */\n addTransitLayer(layer: AgmTransitLayer): void {\n const newLayer = this._wrapper.createTransitLayer();\n this._layers.set(layer, newLayer);\n }\n\n /**\n * Adds a bicycling layer to a map instance.\n * @param layer - a bicycling layer object\n * @param _options - BicyclingLayer options\n * @returns void\n */\n addBicyclingLayer(layer: AgmBicyclingLayer): void {\n const newLayer = this._wrapper.createBicyclingLayer();\n this._layers.set(layer, newLayer);\n }\n\n /**\n * Deletes a map layer\n * @param layer - the layer to delete\n */\n deleteLayer(layer: AgmTransitLayer | AgmBicyclingLayer): Promise<void> {\n return this._layers.get(layer).then(currentLayer => {\n currentLayer.setMap(null);\n this._layers.delete(layer);\n });\n }\n}\n","import { MapsAPILoader } from './maps-api-loader';\n\n/**\n * When using the NoOpMapsAPILoader, the Google Maps API must be added to the page via a `<script>`\n * Tag.\n * It's important that the Google Maps API script gets loaded first on the page.\n */\nexport class NoOpMapsAPILoader implements MapsAPILoader {\n load(): Promise<void> {\n if (!(window as any).google || !(window as any).google.maps) {\n throw new Error(\n 'Google Maps API not loaded on page. Make sure window.google.maps is available!');\n }\n return Promise.resolve();\n }\n}\n","import { fromEventPattern, Observable } from 'rxjs';\n\nexport function createMVCEventObservable<T>(array: google.maps.MVCArray<T>): Observable<MVCEvent<T>>{\n const eventNames = ['insert_at', 'remove_at', 'set_at'];\n return fromEventPattern(\n handler => eventNames.map(eventName => array.addListener(eventName,\n (index: number, previous?: T) => handler.apply(array, [ {newArr: array.getArray(), eventName, index, previous} as MVCEvent<T>]))),\n (_handler, evListeners: google.maps.MapsEventListener[]) => evListeners.forEach(evListener => evListener.remove()));\n}\n\nexport type MvcEventType = 'insert_at' | 'remove_at' | 'set_at';\n\nexport interface MVCEvent<T> {\n newArr: T[];\n eventName: MvcEventType;\n index: number;\n previous?: T;\n}\n\nexport class MvcArrayMock<T> implements google.maps.MVCArray<T> {\n private vals: T[] = [];\n private listeners: {\n 'remove_at': ((i: number, r: T) => void)[];\n 'insert_at': ((i: number) => void)[];\n 'set_at': ((i: number, val: T) => void)[];\n } = {\n remove_at: [],\n insert_at: [],\n set_at: [],\n };\n clear(): void {\n for (let i = this.vals.length - 1; i >= 0; i--) {\n this.removeAt(i);\n }\n }\n getArray(): T[] {\n return [...this.vals];\n }\n getAt(i: number): T {\n return this.vals[i];\n }\n getLength(): number {\n return this.vals.length;\n }\n insertAt(i: number, elem: T): void {\n this.vals.splice(i, 0, elem);\n this.listeners.insert_at.forEach(listener => listener(i));\n }\n pop(): T {\n const deleted = this.vals.pop();\n this.listeners.remove_at.forEach(listener => listener(this.vals.length, deleted));\n return deleted;\n }\n push(elem: T): number {\n this.vals.push(elem);\n this.listeners.insert_at.forEach(listener => listener(this.vals.length - 1));\n return this.vals.length;\n }\n removeAt(i: number): T {\n const deleted = this.vals.splice(i, 1)[0];\n this.listeners.remove_at.forEach(listener => listener(i, deleted));\n return deleted;\n }\n setAt(i: number, elem: T): void {\n const deleted = this.vals[i];\n this.vals[i] = elem;\n this.listeners.set_at.forEach(listener => listener(i, deleted));\n }\n forEach(callback: (elem: T, i: number) => void): void {\n this.vals.forEach(callback);\n }\n addListener(eventName: 'remove_at' | 'insert_at' | 'set_at', handler: (...args: any[]) => void): google.maps.MapsEventListener {\n const listenerArr = this.listeners[eventName];\n listenerArr.push(handler);\n return {\n remove: () => {\n listenerArr.splice(listenerArr.indexOf(handler), 1);\n },\n };\n }\n\n bindTo(): never { throw new Error('Not implemented'); }\n changed(): never { throw new Error('Not implemented'); }\n get(): never { throw new Error('Not implemented'); }\n notify(): never { throw new Error('Not implemented'); }\n set(): never { throw new Error('Not implemented'); }\n setValues(): never { throw new Error('Not implemented'); }\n unbind(): never { throw new Error('Not implemented'); }\n unbindAll(): never { throw new Error('Not implemented'); }\n}\n","import { Injectable, NgZone } from '@angular/core';\nimport { merge, Observable, Observer } from 'rxjs';\nimport { map, skip, startWith, switchMap } from 'rxjs/operators';\n\nimport { AgmPolygon } from '../../directives/polygon';\nimport { createMVCEventObservable, MVCEvent } from '../../utils/mvcarray-utils';\nimport { GoogleMapsAPIWrapper } from '../google-maps-api-wrapper';\n\n@Injectable()\nexport class PolygonManager {\n private _polygons: Map<AgmPolygon, Promise<google.maps.Polygon>> =\n new Map<AgmPolygon, Promise<google.maps.Polygon>>();\n\n constructor(private _mapsWrapper: GoogleMapsAPIWrapper, private _zone: NgZone) { }\n\n addPolygon(path: AgmPolygon) {\n const polygonPromise = this._mapsWrapper.createPolygon({\n clickable: path.clickable,\n draggable: path.draggable,\n editable: path.editable,\n fillColor: path.fillColor,\n fillOpacity: path.fillOpacity,\n geodesic: path.geodesic,\n paths: path.paths,\n strokeColor: path.strokeColor,\n strokeOpacity: path.strokeOpacity,\n strokeWeight: path.strokeWeight,\n visible: path.visible,\n zIndex: path.zIndex,\n });\n this._polygons.set(path, polygonPromise);\n }\n\n updatePolygon(polygon: AgmPolygon): Promise<void> {\n const m = this._polygons.get(polygon);\n if (m == null) {\n return Promise.resolve();\n }\n return m.then((l: google.maps.Polygon) => this._zone.run(() => { l.setPaths(polygon.paths); }));\n }\n\n setPolygonOptions(path: AgmPolygon, options: { [propName: string]: any }): Promise<void> {\n return this._polygons.get(path).then((l: google.maps.Polygon) => { l.setOptions(options); });\n }\n\n deletePolygon(paths: AgmPolygon): Promise<void> {\n const m = this._polygons.get(paths);\n if (m == null) {\n return Promise.resolve();\n }\n return m.then((l: google.maps.Polygon) => {\n return this._zone.run(() => {\n l.setMap(null);\n this._polygons.delete(paths);\n });\n });\n }\n\n getPath(polygonDirective: AgmPolygon): Promise<google.maps.LatLng[]> {\n return this._polygons.get(polygonDirective)\n .then((polygon) => polygon.getPath().getArray());\n }\n\n getPaths(polygonDirective: AgmPolygon): Promise<google.maps.LatLng[][]> {\n return this._polygons.get(polygonDirective)\n .then((polygon) => polygon.getPaths().getArray().map((p) => p.getArray()));\n }\n\n createEventObservable<T>(eventName: string, path: AgmPolygon): Observable<T> {\n return new Observable((observer: Observer<T>) => {\n this._polygons.get(path).then((l: google.maps.Polygon) => {\n l.addListener(eventName, (e: T) => this._zone.run(() => observer.next(e)));\n });\n });\n }\n\n async createPathEventObservable(agmPolygon: AgmPolygon):\n Promise<Observable<MVCEvent<google.maps.LatLng[] | google.maps.LatLngLiteral[]>>> {\n const polygon = await this._polygons.get(agmPolygon);\n const paths = polygon.getPaths();\n const pathsChanges$ = createMVCEventObservable(paths);\n return pathsChanges$.pipe(\n startWith(({ newArr: paths.getArray() } as MVCEvent<google.maps.MVCArray<google.maps.LatLng>>)), // in order to subscribe to them all\n switchMap(parentMVEvent => merge(...// rest parameter\n parentMVEvent.newArr.map((chMVC, index) =>\n createMVCEventObservable(chMVC)\n .pipe(map(chMVCEvent => ({ parentMVEvent, chMVCEvent, pathIndex: index })))))\n .pipe( // start the merged ob with an event signinifing change to parent\n startWith({ parentMVEvent, chMVCEvent: null, pathIndex: null }))\n ),\n skip(1), // skip the manually added event\n map(({ parentMVEvent, chMVCEvent, pathIndex }) => {\n let retVal;\n if (!chMVCEvent) {\n retVal = {\n newArr: parentMVEvent.newArr.map(subArr => subArr.getArray().map(latLng => latLng.toJSON())),\n eventName: parentMVEvent.eventName,\n index: parentMVEvent.index,\n } as MVCEvent<google.maps.LatLng[] | google.maps.LatLngLiteral[]>;\n if (parentMVEvent.previous) {\n retVal.previous = parentMVEvent.previous.getArray();\n }\n } else {\n retVal = {\n newArr: parentMVEvent.newArr.map(subArr => subArr.getArray().map(latLng => latLng.toJSON())),\n pathIndex,\n eventName: chMVCEvent.eventName,\n index: chMVCEvent.index,\n } as unknown as MVCEvent<google.maps.LatLng[] | google.maps.LatLngLiteral[]>;\n if (chMVCEvent.previous) {\n retVal.previous = chMVCEvent.previous;\n }\n }\n return retVal;\n }));\n }\n}\n","import { Injectable, NgZone } from '@angular/core';\nimport { Observable, Observer } from 'rxjs';\n\nimport { AgmPolyline } from '../../directives/polyline';\nimport { AgmPolylinePoint } from '../../directives/polyline-point';\nimport { createMVCEventObservable, MVCEvent } from '../../utils/mvcarray-utils';\nimport { GoogleMapsAPIWrapper } from '../google-maps-api-wrapper';\n\n@Injectable()\nexport class PolylineManager {\n private _polylines: Map<AgmPolyline, Promise<google.maps.Polyline>> =\n new Map<AgmPolyline, Promise<google.maps.Polyline>>();\n\n constructor(private _mapsWrapper: GoogleMapsAPIWrapper, private _zone: NgZone) {}\n\n private static _convertPoints(line: AgmPolyline): google.maps.LatLngLiteral[] {\n const path = line._getPoints().map((point: AgmPolylinePoint) => {\n return {lat: point.latitude, lng: point.longitude} as google.maps.LatLngLiteral;\n });\n return path;\n }\n\n private static _convertPath(path: keyof typeof google.maps.SymbolPath | string): google.maps.SymbolPath | string {\n const symbolPath = google.maps.SymbolPath[path as keyof typeof google.maps.SymbolPath];\n if (typeof symbolPath === 'number') {\n return symbolPath;\n } else{\n return path;\n }\n }\n\n private static _convertIcons(line: AgmPolyline): Array<google.maps.IconSequence> {\n const icons = line._getIcons().map(agmIcon => ({\n fixedRotation: agmIcon.fixedRotation,\n offset: agmIcon.offset,\n repeat: agmIcon.repeat,\n icon: {\n anchor: new google.maps.Point(agmIcon.anchorX, agmIcon.anchorY),\n fillColor: agmIcon.fillColor,\n fillOpacity: agmIcon.fillOpacity,\n path: PolylineManager._convertPath(agmIcon.path),\n rotation: agmIcon.rotation,\n scale: agmIcon.scale,\n strokeColor: agmIcon.strokeColor,\n strokeOpacity: agmIcon.strokeOpacity,\n strokeWeight: agmIcon.strokeWeight,\n },\n } as google.maps.IconSequence));\n // prune undefineds;\n icons.forEach(icon => {\n Object.entries(icon).forEach(([key, val]) => {\n if (typeof val === 'undefined') {\n delete (icon as any)[key];\n }\n });\n if (typeof icon.icon.anchor.x === 'undefined' ||\n typeof icon.icon.anchor.y === 'undefined') {\n delete icon.icon.anchor;\n }\n });\n return icons;\n }\n\n addPolyline(line: AgmPoly