@ng-maps/google
Version:
**@ng-maps/google** is a simple, modular and tree-shakable library for displaying google-maps inside an angular application
1,062 lines (1,045 loc) • 41 kB
JavaScript
import * as i0 from '@angular/core';
import { Injectable, Component, InjectionToken, Optional, Inject, NgModule } from '@angular/core';
import { Observable, ReplaySubject, firstValueFrom } from 'rxjs';
import * as i1 from '@ng-maps/core';
import { MapsApiWrapper, MarkerManager, CircleManager, PolygonManager, PolylineManager, RectangleManager, InfoWindowManager, FitBoundsService, NgMapsViewComponent, MapsAPILoader, MAP_PROVIDER } from '@ng-maps/core';
import { DOCUMENT } from '@angular/common';
/**
* Wrapper class that handles the communication with the Google Maps Javascript
* API v3
*/
class GoogleMapsAPIWrapper extends MapsApiWrapper {
constructor(_loader, _zone) {
super(_loader, _zone);
}
createMap(el, center, options) {
return this._zone.runOutsideAngular(async () => {
await this._loader.load();
if (this._mapResolver) {
this._mapResolver(new google.maps.Map(el, { center, ...options }));
}
return;
});
}
async setMapOptions(options) {
const map = await this._api;
map?.setOptions(options);
}
/**
* Creates a google map drawing manager with the map context
*/
async createDrawingManager(options = {}, addToMap = true) {
const map = await this._api;
if (addToMap) {
options.map = map;
}
return new google.maps.drawing.DrawingManager(options);
}
/**
* Creates a google map marker with the map context
*/
async createMarker(position, options, addToMap = true) {
const map = addToMap ? await this._api : null;
return new google.maps.Marker({ position, map, ...options });
}
async createInfoWindow(position, options) {
await this._api;
if (position === null) {
return new google.maps.InfoWindow({ ...options });
}
else {
return new google.maps.InfoWindow({ position: position, ...options });
}
}
/**
* Creates a google.map.Circle for the current map.
*
* @todo check how to improve type casting
*/
async createCircle(center, options) {
const opt = {
...options,
center,
map: await this._api,
};
if (typeof opt.strokePosition === 'string') {
opt.strokePosition = google.maps.StrokePosition[opt.strokePosition];
}
return new google.maps.Circle(opt);
}
/**
* Creates a google.map.Rectangle for the current map.
*/
async createRectangle(bounds, options) {
const map = await this._api;
return new google.maps.Rectangle({
...options,
bounds,
map,
});
}
async createPolyline(options) {
return this.getNativeMap().then((map) => {
const line = new google.maps.Polyline(options);
if (map) {
line.setMap(map);
}
return line;
});
}
createPolygon(options) {
return this.getNativeMap().then((map) => {
const polygon = new google.maps.Polygon(options);
if (map) {
polygon.setMap(map);
}
return polygon;
});
}
/**
* Creates a new google.map.Data layer for the current map
*/
async createDataLayer(options) {
return this._api?.then((m) => {
const data = new google.maps.Data(options);
data.setMap(m);
return data;
});
}
/**
* Determines if given coordinates are insite a Polygon path.
*/
containsLocation(latLng, polygon) {
return google.maps.geometry.poly.containsLocation(latLng, polygon);
}
/**
* @fixme typings
*/
subscribeToMapEvent(eventName) {
return new Observable((observer) => {
this._api?.then((m) => m.addListener(eventName, (...evArgs) => this._zone.run(() => observer.next(evArgs))));
});
}
clearInstanceListeners() {
this._api?.then((map) => {
google.maps.event.clearInstanceListeners(map);
});
}
async setCenter(latLng) {
return this._api?.then((map) => map.setCenter(latLng));
}
async getZoom() {
const map = await this._api;
return map?.getZoom();
}
async getBounds() {
const map = await this._api;
return map?.getBounds()?.toJSON();
}
async getMapTypeId() {
return this._api?.then((map) => map.getMapTypeId());
}
async setZoom(zoom) {
this._api?.then((map) => map.setZoom(zoom));
}
async getCenter() {
const map = await this._api;
return map?.getCenter()?.toJSON();
}
async panTo(latLng) {
this._api?.then((map) => map.panTo(latLng));
}
async panBy(x, y) {
this._api?.then((map) => map.panBy(x, y));
}
async fitBounds(latLng, padding) {
const map = await this._api;
map?.fitBounds(latLng, padding);
}
async panToBounds(latLng, padding) {
const map = await this._api;
return map?.panToBounds(latLng, padding);
}
/**
* Triggers the given event name on the map instance.
*/
async triggerMapEvent(eventName) {
const map = await this._api;
if (map) {
google.maps.event.trigger(map, eventName);
}
}
_isLatLngBoundsLiteral(bounds) {
return bounds != null && bounds.extend === undefined;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GoogleMapsAPIWrapper, deps: [{ token: i1.MapsAPILoader }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GoogleMapsAPIWrapper }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GoogleMapsAPIWrapper, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.MapsAPILoader }, { type: i0.NgZone }] });
function isValidMarkerIcon(marker) {
if (marker === null) {
return true;
}
else if (typeof marker === 'string') {
return true;
}
else if (typeof marker === 'object' && Object.hasOwn(marker, 'url')) {
return true;
}
else if (typeof marker === 'object' && Object.hasOwn(marker, 'path')) {
return true;
}
else {
return false;
}
}
class GoogleMapsMarkerManager extends MarkerManager {
constructor(_mapsWrapper, _zone) {
super(_mapsWrapper, _zone);
this._markers = new Map();
}
deleteMarker(marker) {
const m = this._markers.get(marker);
if (m == null) {
// marker already deleted
return;
}
else {
return this._zone.run(() => {
m.setMap(null);
this._markers.delete(marker);
});
}
}
updateMarkerPosition(marker) {
if (typeof marker.latitude !== 'number' ||
typeof marker.longitude !== 'number') {
return;
}
const m = this._markers.get(marker);
m?.setPosition({ lat: marker.latitude, lng: marker.longitude });
}
updateTitle(marker) {
const m = this._markers.get(marker);
m?.setTitle(marker.title);
}
updateLabel(marker) {
const m = this._markers.get(marker);
m?.setLabel(marker.label);
}
updateDraggable(marker) {
const m = this._markers.get(marker);
m?.setDraggable(marker.draggable);
}
updateIconLegacy(marker) {
const m = this._markers.get(marker);
m?.setIcon(marker.iconUrl);
}
updateOpacity(marker) {
const m = this._markers.get(marker);
m?.setOpacity(marker.opacity);
}
updateVisible(marker) {
const m = this._markers.get(marker);
m?.setVisible(marker.visible);
}
updateZIndex(marker) {
const m = this._markers.get(marker);
m?.setZIndex(marker.zIndex);
}
updateClickable(marker) {
const m = this._markers.get(marker);
m?.setClickable(marker.clickable);
}
updateAnimation(marker) {
const m = this._markers.get(marker);
if (typeof marker.animation === 'string') {
m?.setAnimation(google.maps.Animation[marker.animation]);
}
else {
m?.setAnimation(marker.animation);
}
}
createEventObservable(eventName, marker) {
return new Observable((observer) => {
const m = this._markers.get(marker);
if (typeof eventName === 'string') {
eventName = [eventName];
}
eventName.forEach((event) => {
m?.addListener(event, (e) => this._zone.run(() => observer.next(e)));
});
});
}
updateIcon(marker) {
const m = this._markers.get(marker);
if (m && isValidMarkerIcon(marker.icon)) {
m.setIcon(marker.icon);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GoogleMapsMarkerManager, deps: [{ token: i1.MapsApiWrapper }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GoogleMapsMarkerManager }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GoogleMapsMarkerManager, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.MapsApiWrapper }, { type: i0.NgZone }] });
class GoogleCircleManager extends CircleManager {
constructor(_mapsWrapper, _zone) {
super(_mapsWrapper, _zone);
}
/**
* @fixme implement commented properties
*/
async addCircle(circle) {
if (!circle.latitude || !circle.longitude) {
return;
}
this._circles.set(circle, this._apiWrapper.createCircle({ lat: circle.latitude, lng: circle.longitude }, {
// clickable: circle.clickable,
// draggable: circle.draggable,
// editable: circle.editable,
fillColor: circle.fillColor,
fillOpacity: circle.fillOpacity,
radius: circle.radius,
strokeColor: circle.strokeColor,
strokeOpacity: circle.strokeOpacity,
// strokePosition: circle.strokePosition,
strokeWeight: circle.strokeWeight,
visible: circle.visible,
zIndex: circle.zIndex,
}));
}
/**
* Removes the given circle from the map.
*/
async removeCircle(circle) {
const c = await this._circles.get(circle);
c?.setMap(null);
this._circles.delete(circle);
}
/**
* @todo check how to improve type casting
* @param circle instance of {@link NgMapsCircleDirective}
* @param options options for the circle
*/
async setOptions(circle, options) {
const c = await this._circles.get(circle);
if (typeof options.strokePosition === 'string') {
options.strokePosition = google.maps.StrokePosition[options.strokePosition];
}
return c?.setOptions(options);
}
async getBounds(circle) {
const c = await this._circles.get(circle);
if (!c) {
return null;
}
const bounds = c.getBounds();
return bounds ? bounds.toJSON() : null;
}
async getCenter(circle) {
const c = await this._circles.get(circle);
const center = c?.getCenter();
return center ? center.toJSON() : null;
}
async getRadius(circle) {
const c = await this._circles.get(circle);
return c?.getRadius() ?? null;
}
async setCenter(circle) {
if (!circle.latitude || !circle.longitude) {
return;
}
const c = await this._circles.get(circle);
c?.setCenter({ lat: circle.latitude, lng: circle.longitude });
}
async setEditable(circle) {
const c = await this._circles.get(circle);
c?.setEditable(circle.editable);
}
async setDraggable(circle) {
const c = await this._circles.get(circle);
c?.setDraggable(circle.draggable);
}
async setVisible(circle) {
const c = await this._circles.get(circle);
c?.setVisible(circle.visible);
}
async setRadius(circle) {
const c = await this._circles.get(circle);
c?.setRadius(circle.radius);
}
createEventObservable(eventName, circle) {
return new Observable((observer) => {
let listener = null;
this._circles?.get(circle)?.then((c) => {
listener = c.addListener(eventName, (e) => this._zone.run(() => observer.next(e)));
});
return () => {
if (listener !== null) {
listener.remove();
}
};
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GoogleCircleManager, deps: [{ token: i1.MapsApiWrapper }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GoogleCircleManager }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GoogleCircleManager, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.MapsApiWrapper }, { type: i0.NgZone }] });
class GooglePolygonManager extends PolygonManager {
constructor(_mapsWrapper, _zone) {
super(_mapsWrapper, _zone);
}
addPolygon(path) {
const polygonPromise = this._mapsWrapper.createPolygon({
clickable: path.clickable,
draggable: path.draggable,
editable: path.editable,
fillColor: path.fillColor,
fillOpacity: path.fillOpacity,
geodesic: path.geodesic,
paths: path.paths,
strokeColor: path.strokeColor,
strokeOpacity: path.strokeOpacity,
strokeWeight: path.strokeWeight,
visible: path.visible,
zIndex: path.zIndex,
});
this._polygons.set(path, polygonPromise);
}
async updatePolygon(polygon) {
const item = await this._polygons.get(polygon);
if (item != null) {
this._zone.run(() => {
item.setPaths(polygon.paths);
});
}
}
async setPolygonOptions(path, options) {
const l = await this._polygons.get(path);
l?.setOptions(options);
}
deletePolygon(paths) {
const m = this._polygons.get(paths);
if (m == null) {
return Promise.resolve();
}
return m.then((l) => this._zone.run(() => {
l.setMap(null);
this._polygons.delete(paths);
}));
}
createEventObservable(eventName, path) {
return new Observable((observer) => {
this._polygons.get(path)?.then((l) => {
l.addListener(eventName, (e) => this._zone.run(() => observer.next(e)));
});
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GooglePolygonManager, deps: [{ token: i1.MapsApiWrapper }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GooglePolygonManager }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GooglePolygonManager, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.MapsApiWrapper }, { type: i0.NgZone }] });
class GooglePolylineManager extends PolylineManager {
constructor(_mapsWrapper, _zone) {
super(_mapsWrapper, _zone);
}
_convertPoints(line) {
return line._getPoints().map((point) => ({
lat: point.latitude,
lng: point.longitude,
}));
}
addPolyline(line) {
const path = this._convertPoints(line);
const polylinePromise = this._mapsWrapper.createPolyline({
clickable: line.clickable,
draggable: line.draggable,
editable: line.editable,
geodesic: line.geodesic,
strokeColor: line.strokeColor,
strokeOpacity: line.strokeOpacity,
strokeWeight: line.strokeWeight,
visible: line.visible,
zIndex: line.zIndex,
icons: line.icons,
path,
});
this._polylines.set(line, polylinePromise);
}
updatePolylinePoints(line) {
const path = this._convertPoints(line);
const m = this._polylines.get(line);
if (m == null) {
return Promise.resolve();
}
return m.then((l) => this._zone.run(() => {
l.setPath(path);
}));
}
async setPolylineOptions(line, options) {
const l = await this._polylines.get(line);
l?.setOptions(options);
}
deletePolyline(line) {
const m = this._polylines.get(line);
if (m == null) {
return Promise.resolve();
}
return m.then((l) => this._zone.run(() => {
l.setMap(null);
this._polylines.delete(line);
}));
}
createEventObservable(eventName, line) {
return new Observable((observer) => {
this._polylines.get(line)?.then((l) => {
l.addListener(eventName, (e) => this._zone.run(() => observer.next(e)));
});
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GooglePolylineManager, deps: [{ token: i1.MapsApiWrapper }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GooglePolylineManager }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GooglePolylineManager, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.MapsApiWrapper }, { type: i0.NgZone }] });
class GoogleRectangleManager extends RectangleManager {
constructor(_mapsWrapper, _zone) {
super(_mapsWrapper, _zone);
}
addRectangle(rectangle) {
if (!rectangle.north ||
!rectangle.east ||
!rectangle.south ||
!rectangle.west) {
return;
}
this._rectangles.set(rectangle, this._apiWrapper.createRectangle({
north: rectangle.north,
east: rectangle.east,
south: rectangle.south,
west: rectangle.west,
}, {
// clickable: rectangle.clickable,
// draggable: rectangle.draggable,
// editable: rectangle.editable,
fillColor: rectangle.fillColor,
fillOpacity: rectangle.fillOpacity,
strokeColor: rectangle.strokeColor,
strokeOpacity: rectangle.strokeOpacity,
// strokePosition: rectangle.strokePosition,
strokeWeight: rectangle.strokeWeight,
visible: rectangle.visible,
zIndex: rectangle.zIndex,
}));
}
/**
* Removes the given rectangle from the map.
*/
async removeRectangle(rectangle) {
return this._rectangles.get(rectangle)?.then((r) => {
r.setMap(null);
this._rectangles.delete(rectangle);
});
}
async setOptions(rectangle, options) {
return this._rectangles.get(rectangle)?.then((r) => r.setOptions(options));
}
async getBounds(rectangle) {
const r = await this._rectangles.get(rectangle);
const bounds = r?.getBounds();
return bounds ? bounds.toJSON() : null;
}
async setBounds(rectangle) {
if (!rectangle.north ||
!rectangle.east ||
!rectangle.south ||
!rectangle.west) {
return;
}
const r = await this._rectangles.get(rectangle);
r?.setBounds({
north: rectangle.north,
east: rectangle.east,
south: rectangle.south,
west: rectangle.west,
});
}
async setEditable(rectangle) {
return this._rectangles
.get(rectangle)
?.then((r) => r.setEditable(rectangle.editable));
}
async setDraggable(rectangle) {
return this._rectangles
.get(rectangle)
?.then((r) => r.setDraggable(rectangle.draggable));
}
async setVisible(rectangle) {
return this._rectangles
.get(rectangle)
?.then((r) => r.setVisible(rectangle.visible));
}
createEventObservable(eventName, rectangle) {
return new Observable((observer) => {
let listener = null;
this._rectangles.get(rectangle)?.then((r) => {
listener = r.addListener(eventName, (e) => this._zone.run(() => observer.next(e)));
});
return () => {
if (listener !== null) {
listener.remove();
}
};
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GoogleRectangleManager, deps: [{ token: i1.MapsApiWrapper }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GoogleRectangleManager }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GoogleRectangleManager, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.MapsApiWrapper }, { type: i0.NgZone }] });
class GoogleInfoWindowManager extends InfoWindowManager {
constructor(_mapsWrapper, _zone, _markerManager) {
super(_mapsWrapper, _zone, _markerManager);
}
async deleteInfoWindow(infoWindow) {
const iWindow = await this._infoWindows.get(infoWindow);
if (iWindow == null) {
// info window already deleted
return;
}
else {
return this._zone.run(() => {
iWindow.close();
this._infoWindows.delete(infoWindow);
});
}
}
setPosition(infoWindow) {
if (!infoWindow.latitude || !infoWindow.longitude) {
return;
}
const i = this._infoWindows.get(infoWindow);
i?.setPosition({
lat: infoWindow.latitude,
lng: infoWindow.longitude,
});
}
setZIndex(infoWindow) {
if (!infoWindow.zIndex) {
return;
}
const i = this._infoWindows.get(infoWindow);
i?.setZIndex(infoWindow.zIndex);
}
async open(infoWindow) {
const w = this._infoWindows.get(infoWindow);
const map = await this._mapsWrapper.getNativeMap();
if (infoWindow.hostMarker != null) {
const marker = await this._markerManager.getNativeMarker(infoWindow.hostMarker);
w?.open(map, marker);
}
else {
w?.open(map);
}
}
close(infoWindow) {
const w = this._infoWindows.get(infoWindow);
w?.close();
}
setOptions(infoWindow, options) {
const i = this._infoWindows.get(infoWindow);
i?.setOptions(options);
}
async addInfoWindow(infoWindow) {
const options = {
content: infoWindow.content?.nativeElement,
maxWidth: infoWindow.maxWidth,
zIndex: infoWindow.zIndex,
disableAutoPan: infoWindow.disableAutoPan,
};
const center = typeof infoWindow.latitude === 'number' &&
typeof infoWindow.longitude === 'number'
? {
lat: infoWindow.latitude,
lng: infoWindow.longitude,
}
: null;
const instance = await this._mapsWrapper.createInfoWindow(center, options);
this._infoWindows.set(infoWindow, instance);
}
/**
* Creates a Google Maps event listener for the given InfoWindow as an Observable
*/
createEventObservable(eventName, infoWindow) {
const i = this._infoWindows.get(infoWindow);
return new Observable((observer) => {
i?.addListener(eventName, (e) => this._zone.run(() => observer.next(e)));
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GoogleInfoWindowManager, deps: [{ token: i1.MapsApiWrapper }, { token: i0.NgZone }, { token: i1.MarkerManager }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GoogleInfoWindowManager }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GoogleInfoWindowManager, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.MapsApiWrapper }, { type: i0.NgZone }, { type: i1.MarkerManager }] });
/**
* The FitBoundsService is responsible for computing the bounds of the a single map.
*/
class GoogleMapsFitBoundsService extends FitBoundsService {
constructor(_loader) {
super(_loader);
}
generateBounds(includeInBounds) {
if (includeInBounds.size === 0) {
return new google.maps.LatLngBounds().toJSON();
}
else {
const bounds = new google.maps.LatLngBounds();
includeInBounds.forEach((b) => bounds.extend(b));
return bounds.toJSON();
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GoogleMapsFitBoundsService, deps: [{ token: i1.MapsAPILoader }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GoogleMapsFitBoundsService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GoogleMapsFitBoundsService, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.MapsAPILoader }] });
class GoogleComponent extends NgMapsViewComponent {
constructor(_mapsWrapper, _fitBoundsService, _zone) {
super(_mapsWrapper, _fitBoundsService, _zone);
}
async _handleMapCenterChange() {
const s = this._mapsWrapper
.subscribeToMapEvent('center_changed')
.subscribe(() => {
this._mapsWrapper.getCenter().then((center) => {
if (center) {
this.latitude = center.lat;
this.longitude = center.lng;
this.centerChange.emit({
lat: this.latitude,
lng: this.longitude,
});
}
});
});
this.subscription.add(s);
}
_handleBoundsChange() {
const s = this._mapsWrapper
.subscribeToMapEvent('bounds_changed')
.subscribe(() => {
this._mapsWrapper.getBounds().then((bounds) => {
this.boundsChange.emit(bounds);
});
});
this.subscription.add(s);
}
async _handleMapTypeIdChange() {
const s = this._mapsWrapper
.subscribeToMapEvent('maptypeid_changed')
.subscribe(() => {
this._mapsWrapper.getMapTypeId().then((mapTypeId) => {
this.mapTypeIdChange.emit(mapTypeId);
});
});
this.subscription.add(s);
}
_handleMapZoomChange() {
const s = this._mapsWrapper
.subscribeToMapEvent('zoom_changed')
.subscribe(() => {
this._mapsWrapper.getZoom().then((z) => {
this.zoom = z ?? 8;
this.zoomChange.emit(z);
});
});
this.subscription.add(s);
}
_handleIdleEvent() {
const s = this._mapsWrapper.subscribeToMapEvent('idle').subscribe(() => {
this.idle.emit(void 0);
});
this.subscription.add(s);
}
_handleTilesLoadedEvent() {
const s = this._mapsWrapper
.subscribeToMapEvent('tilesloaded')
.subscribe(() => this.tilesLoaded.emit(void 0));
this.subscription.add(s);
}
_handleMapMouseEvents() {
const events = [
{ name: 'click', emitter: this.mapClick },
{ name: 'rightclick', emitter: this.mapRightClick },
{ name: 'dblclick', emitter: this.mapDblClick },
];
events.forEach((e) => {
const s = this._mapsWrapper
.subscribeToMapEvent(e.name)
.subscribe((event) => {
const value = {
coords: { lat: event[0].latLng.lat(), lng: event[0].latLng.lng() },
};
e.emitter.emit(value);
});
this.subscription.add(s);
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GoogleComponent, deps: [{ token: i1.MapsApiWrapper }, { token: i1.FitBoundsService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.8", type: GoogleComponent, selector: "map-view", providers: [
{ provide: MapsApiWrapper, useClass: GoogleMapsAPIWrapper },
{ provide: FitBoundsService, useClass: GoogleMapsFitBoundsService },
{ provide: MarkerManager, useClass: GoogleMapsMarkerManager },
{ provide: CircleManager, useClass: GoogleCircleManager },
{ provide: PolygonManager, useClass: GooglePolygonManager },
{ provide: PolylineManager, useClass: GooglePolylineManager },
{ provide: RectangleManager, useClass: GoogleRectangleManager },
{ provide: InfoWindowManager, useClass: GoogleInfoWindowManager },
], usesInheritance: true, ngImport: i0, template: `
<div class="map-container-inner" #container></div>
<div class="map-content">
<ng-content></ng-content>
</div>
`, isInline: true, styles: [".map-container-inner{width:inherit;height:inherit}.map-content{display:none}\n"] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GoogleComponent, decorators: [{
type: Component,
args: [{ selector: 'map-view', providers: [
{ provide: MapsApiWrapper, useClass: GoogleMapsAPIWrapper },
{ provide: FitBoundsService, useClass: GoogleMapsFitBoundsService },
{ provide: MarkerManager, useClass: GoogleMapsMarkerManager },
{ provide: CircleManager, useClass: GoogleCircleManager },
{ provide: PolygonManager, useClass: GooglePolygonManager },
{ provide: PolylineManager, useClass: GooglePolylineManager },
{ provide: RectangleManager, useClass: GoogleRectangleManager },
{ provide: InfoWindowManager, useClass: GoogleInfoWindowManager },
], template: `
<div class="map-container-inner" #container></div>
<div class="map-content">
<ng-content></ng-content>
</div>
`, styles: [".map-container-inner{width:inherit;height:inherit}.map-content{display:none}\n"] }]
}], ctorParameters: () => [{ type: i1.MapsApiWrapper }, { type: i1.FitBoundsService }, { type: i0.NgZone }] });
var GoogleMapsScriptProtocol;
(function (GoogleMapsScriptProtocol) {
GoogleMapsScriptProtocol[GoogleMapsScriptProtocol["HTTP"] = 1] = "HTTP";
GoogleMapsScriptProtocol[GoogleMapsScriptProtocol["HTTPS"] = 2] = "HTTPS";
GoogleMapsScriptProtocol[GoogleMapsScriptProtocol["AUTO"] = 3] = "AUTO";
})(GoogleMapsScriptProtocol || (GoogleMapsScriptProtocol = {}));
/**
* Token for the config of google maps module
* Please provide an object of type {@link GoogleModuleOptions}.
*/
const GOOGLE_MAPS_API_CONFIG = new InjectionToken('angular-google-maps GOOGLE_MAPS_API_CONFIG');
class GoogleMapsScriptLoader extends MapsAPILoader {
constructor(config, document) {
super();
this._config = new ReplaySubject(1);
this._SCRIPT_ID = 'GoogleMapsApiScript';
this.callbackName = `LazyMapsAPILoader`;
if (config instanceof Promise) {
config.then((c) => {
this.configure(c);
});
}
else if (typeof config === 'object') {
this.configure(config);
}
this._document = document;
this._window = this._document.defaultView;
}
/**
* If no configuration is provided at load time you can use this function to provide configuration at any time.
* Loading scripts will be postponed until a configuration is provided
*
* @param config - {@link GoogleModuleOptions} configuration needed for bootstrapping
*/
configure(config) {
this._config.next(config);
this._config.complete();
}
load() {
if (this._window.google && this._window.google.maps) {
// Google maps already loaded on the page
return Promise.resolve();
}
else if (this._scriptLoadingPromise) {
return this._scriptLoadingPromise;
}
else {
this._scriptLoadingPromise = this.checkScriptElement();
return this._scriptLoadingPromise;
}
}
async checkScriptElement() {
let scriptElement = this._document?.getElementById(this._SCRIPT_ID);
if (scriptElement == null) {
scriptElement = await this.createScriptElement();
}
return this.assignScriptLoadingPromise(scriptElement);
}
assignScriptLoadingPromise(scriptElement) {
this._document?.body.appendChild(scriptElement);
return new Promise((resolve, reject) => {
// FIXME
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
this._window[this.callbackName] = () => resolve();
// FIXME
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
scriptElement.onerror = (error) => reject(error);
});
}
async createScriptElement() {
if (!this._document) {
throw new Error('Document is not defined');
}
const script = this._document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.defer = true;
script.id = this._SCRIPT_ID;
script.src = await this._getScriptSrc(this.callbackName);
return script;
}
async _getScriptSrc(callbackName) {
const config = await firstValueFrom(this._config);
if (!config) {
throw new Error('No configuration provided');
}
const protocolType = (config && config.protocol) || GoogleMapsScriptProtocol.HTTPS;
let protocol;
switch (protocolType) {
case GoogleMapsScriptProtocol.AUTO:
protocol = '';
break;
case GoogleMapsScriptProtocol.HTTP:
protocol = 'http:';
break;
case GoogleMapsScriptProtocol.HTTPS:
protocol = 'https:';
break;
}
const hostAndPath = config.hostAndPath || 'maps.googleapis.com/maps/api/js';
const queryParams = {
v: config.apiVersion || 'quarterly',
callback: callbackName,
key: config.apiKey,
client: config.clientId,
channel: config.channel,
libraries: config.libraries,
region: config.region,
language: config.language,
};
const params = Object.keys(queryParams)
.filter((k) => queryParams[k] != null)
.filter((k) =>
// remove empty arrays
!Array.isArray(queryParams[k]) ||
(Array.isArray(queryParams[k]) && queryParams[k].length > 0))
.map((k) => {
// join arrays as comma seperated strings
const i = queryParams[k];
if (Array.isArray(i)) {
return { key: k, value: i.join(',') };
}
return { key: k, value: queryParams[k] };
})
.map(
// FIXME
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
(entry) => `${entry.key}=${entry.value}`)
.join('&');
return `${protocol}//${hostAndPath}?${params}`;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GoogleMapsScriptLoader, deps: [{ token: GOOGLE_MAPS_API_CONFIG, optional: true }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GoogleMapsScriptLoader }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: GoogleMapsScriptLoader, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [GOOGLE_MAPS_API_CONFIG]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }] });
class NgMapsGoogleModule {
/**
* configure the NgMapsGoogleModule with a value
* @param config
*/
static forRoot(config) {
return {
ngModule: NgMapsGoogleModule,
providers: [
{
provide: GOOGLE_MAPS_API_CONFIG,
useValue: config,
},
],
};
}
/**
* configure the NgMapsGoogleModule with a factory
* @param factory
*/
static forRootFactory(factory, deps) {
return {
ngModule: NgMapsGoogleModule,
providers: [
{
provide: GOOGLE_MAPS_API_CONFIG,
useFactory: factory,
deps,
},
],
};
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: NgMapsGoogleModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.8", ngImport: i0, type: NgMapsGoogleModule, declarations: [GoogleComponent], exports: [GoogleComponent] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: NgMapsGoogleModule, providers: [
{ provide: MapsAPILoader, useClass: GoogleMapsScriptLoader },
{
provide: MAP_PROVIDER,
useValue: 'GoogleMaps',
},
] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: NgMapsGoogleModule, decorators: [{
type: NgModule,
args: [{
declarations: [GoogleComponent],
exports: [GoogleComponent],
providers: [
{ provide: MapsAPILoader, useClass: GoogleMapsScriptLoader },
{
provide: MAP_PROVIDER,
useValue: 'GoogleMaps',
},
],
}]
}] });
/*
* Public API Surface of google
*/
/**
* Generated bundle index. Do not edit.
*/
export { GOOGLE_MAPS_API_CONFIG, GoogleCircleManager, GoogleComponent, GoogleInfoWindowManager, GoogleMapsAPIWrapper, GoogleMapsMarkerManager, GoogleMapsScriptProtocol, GooglePolygonManager, GooglePolylineManager, GoogleRectangleManager, NgMapsGoogleModule, isValidMarkerIcon };
//# sourceMappingURL=ng-maps-google.mjs.map