@boldadmin/angular-google-maps
Version:
Google Maps adapter for Angular Framework
709 lines (696 loc) • 21.6 kB
JavaScript
import { Injectable, Component, Output, NgModule } from '@angular/core';
import { EventPublisher } from '@boldadmin/event-publisher';
import { utc } from 'moment';
import { MatIconRegistry, MatIconModule } from '@angular/material';
import { DomSanitizer } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import GoogleMapsApi from 'load-google-maps-api';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @type {?} */
const mapsText = {
searchBox: 'Search Box'
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class Coordinates {
/**
* @param {?} latitude
* @param {?} longitude
*/
constructor(latitude, longitude) {
this.latitude = latitude;
this.longitude = longitude;
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class Location {
/**
* @param {?} coordinates
* @param {?} radiusInMeters
*/
constructor(coordinates, radiusInMeters) {
this.coordinates = coordinates;
this.radiusInMeters = radiusInMeters;
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class GoogleMapsFactory {
/**
* @return {?}
*/
getGoogleMaps() {
return google.maps;
}
/**
* @param {?} options
* @return {?}
*/
createMap(options) {
return new google.maps.Map(document.getElementById('map'), options);
}
/**
* @param {?} options
* @return {?}
*/
createCircle(options) {
return new google.maps.Circle(options);
}
/**
* @param {?} options
* @return {?}
*/
createMarker(options) {
return new google.maps.Marker(options);
}
/**
* @param {?} options
* @return {?}
*/
createPolyline(options) {
return new google.maps.Polyline(options);
}
/**
* @return {?}
*/
createSearchBox() {
return new google.maps.places.SearchBox((/** @type {?} */ (document.getElementById('search-input'))));
}
/**
* @param {?} coordinates
* @return {?}
*/
createLatLng(coordinates) {
return new google.maps.LatLng(coordinates.latitude, coordinates.longitude);
}
/**
* @return {?}
*/
createGeocoder() {
return new google.maps.Geocoder();
}
/**
* @return {?}
*/
getSearchBoxInput() {
return (/** @type {?} */ (document.getElementById('search-input')));
}
/**
* @param {?} width
* @param {?} height
* @return {?}
*/
createSize(width, height) {
return new google.maps.Size(width, height);
}
/**
* @param {?} x
* @param {?} y
* @return {?}
*/
createPoint(x, y) {
return new google.maps.Point(x, y);
}
}
GoogleMapsFactory.decorators = [
{ type: Injectable }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class AngularGoogleMapsGeocoder {
/**
* @param {?} googleMaps
*/
constructor(googleMaps) {
this.googleMaps = googleMaps;
}
/**
* @param {?} address
* @param {?} callback
* @return {?}
*/
geocode(address, callback) {
return this.googleMaps.createGeocoder().geocode({ 'address': address }, (/**
* @param {?} results
* @return {?}
*/
results => {
if (results !== null && results[0])
callback(new Coordinates(results[0].geometry.location.lat(), results[0].geometry.location.lng()));
else
callback(new Coordinates(59.9139, 10.7522));
}));
}
/**
* @param {?} coordinates
* @param {?} callback
* @return {?}
*/
reverseGeocode(coordinates, callback) {
/** @type {?} */
const latLng = this.googleMaps.createLatLng(coordinates);
this.googleMaps.createGeocoder().geocode({ 'location': latLng }, (/**
* @param {?} results
* @return {?}
*/
results => {
if (results !== null && results[0])
callback(results[0].formatted_address);
else
callback(latLng.toString());
}));
}
}
AngularGoogleMapsGeocoder.decorators = [
{ type: Injectable }
];
/** @nocollapse */
AngularGoogleMapsGeocoder.ctorParameters = () => [
{ type: GoogleMapsFactory }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class AngularGoogleMapsBuilder {
/**
* @param {?} googleMapsFactory
* @param {?} geocoder
* @param {?} eventPublisher
*/
constructor(googleMapsFactory, geocoder, eventPublisher) {
this.googleMapsFactory = googleMapsFactory;
this.geocoder = geocoder;
this.eventPublisher = eventPublisher;
}
/**
* @template THIS
* @this {THIS}
* @param {?} mapOptions
* @return {THIS}
*/
createMap(mapOptions) {
(/** @type {?} */ (this)).map = (/** @type {?} */ (this)).googleMapsFactory.createMap(mapOptions);
return (/** @type {?} */ (this));
}
/**
* @template THIS
* @this {THIS}
* @param {?} markerOptions
* @return {THIS}
*/
addCenterMarker(markerOptions) {
(/** @type {?} */ (this)).marker = (/** @type {?} */ (this)).googleMapsFactory.createMarker(markerOptions);
(/** @type {?} */ (this)).marker.setPosition((/** @type {?} */ (this)).map.getCenter());
(/** @type {?} */ (this)).marker.setMap((/** @type {?} */ (this)).map);
(/** @type {?} */ (this)).addMarkerListeners();
return (/** @type {?} */ (this));
}
/**
* @template THIS
* @this {THIS}
* @param {?} circleOptions
* @return {THIS}
*/
addCircle(circleOptions) {
(/** @type {?} */ (this)).circle = (/** @type {?} */ (this)).googleMapsFactory.createCircle(circleOptions);
(/** @type {?} */ (this)).circle.setMap((/** @type {?} */ (this)).map);
(/** @type {?} */ (this)).circle.addListener('radius_changed', (/**
* @return {?}
*/
() => (/** @type {?} */ (this)).notifyLocationChange()));
return (/** @type {?} */ (this));
}
/**
* @template THIS
* @this {THIS}
* @param {?} polylineOptions
* @return {THIS}
*/
addPolyline(polylineOptions) {
/** @type {?} */
const polyline = (/** @type {?} */ (this)).googleMapsFactory.createPolyline(polylineOptions);
polyline.setMap((/** @type {?} */ (this)).map);
return (/** @type {?} */ (this));
}
/**
* @template THIS
* @this {THIS}
* @param {?} markerOptions
* @return {THIS}
*/
addMarker(markerOptions) {
/** @type {?} */
const marker = (/** @type {?} */ (this)).googleMapsFactory.createMarker(markerOptions);
marker.setMap((/** @type {?} */ (this)).map);
return (/** @type {?} */ (this));
}
/**
* @template THIS
* @this {THIS}
* @return {THIS}
*/
bindCircleToMarker() {
(/** @type {?} */ (this)).circle.bindTo('center', (/** @type {?} */ (this)).marker, 'position');
return (/** @type {?} */ (this));
}
/**
* @template THIS
* @this {THIS}
* @return {THIS}
*/
hideMarker() {
(/** @type {?} */ (this)).marker.setMap(null);
return (/** @type {?} */ (this));
}
/**
* @template THIS
* @this {THIS}
* @return {THIS}
*/
hideCircle() {
(/** @type {?} */ (this)).circle.setMap(null);
return (/** @type {?} */ (this));
}
/**
* @template THIS
* @this {THIS}
* @return {THIS}
*/
addSearchBox() {
/** @type {?} */
const box = (/** @type {?} */ (this)).googleMapsFactory.createSearchBox();
box.addListener('places_changed', (/**
* @return {?}
*/
() => {
/** @type {?} */
const places = box.getPlaces();
if (places[0]) {
(/** @type {?} */ (this)).changeMapLocationAndZoom(places[0].geometry.location);
(/** @type {?} */ (this)).changeMarkerLocation(places[0].geometry.location);
/** @type {?} */
const loc = places[0].geometry.location;
/** @type {?} */
const coordinates = new Coordinates(loc.lat(), loc.lng());
(/** @type {?} */ (this)).eventPublisher.notify('locationChanged', new Location(coordinates, (/** @type {?} */ (this)).circle.getRadius()));
}
}));
return (/** @type {?} */ (this));
}
/**
* @private
* @return {?}
*/
addMarkerListeners() {
this.marker.addListener('dragend', (/**
* @return {?}
*/
() => this.notifyLocationChange()));
this.marker.addListener('dragend', (/**
* @param {?} mouseEvent
* @return {?}
*/
mouseEvent => this.reverseGeocode(mouseEvent)));
this.map.addListener('click', (/**
* @param {?} mouseEvent
* @return {?}
*/
mouseEvent => this.changeMarkerLocation(mouseEvent.latLng)));
this.map.addListener('click', (/**
* @return {?}
*/
() => this.notifyLocationChange()));
this.map.addListener('click', (/**
* @param {?} mouseEvent
* @return {?}
*/
mouseEvent => this.reverseGeocode(mouseEvent)));
}
/**
* @private
* @return {?}
*/
notifyLocationChange() {
this.eventPublisher.notify('locationChanged', new Location(this.getCoordinates(), this.getRadius()));
}
/**
* @private
* @return {?}
*/
getRadius() {
/** @type {?} */
let radiusInMeters = 0;
if (this.circle !== undefined)
radiusInMeters = this.circle.getRadius();
return radiusInMeters;
}
/**
* @private
* @return {?}
*/
getCoordinates() {
/** @type {?} */
let coordinates = new Coordinates(0, 0);
if (this.marker !== undefined)
coordinates = new Coordinates(this.marker.getPosition().lat(), this.marker.getPosition().lng());
return coordinates;
}
/**
* @private
* @param {?} location
* @return {?}
*/
changeMapLocationAndZoom(location) {
this.map.panTo(location);
this.map.setZoom(16);
}
/**
* @private
* @param {?} location
* @return {?}
*/
changeMarkerLocation(location) {
this.circle.setMap(this.map);
this.marker.setMap(this.map);
this.marker.setPosition(location);
}
/**
* @private
* @param {?} e
* @return {?}
*/
reverseGeocode(e) {
this.geocoder.reverseGeocode(new Coordinates(e.latLng.lat(), e.latLng.lng()), (/**
* @param {?} address
* @return {?}
*/
(address) => this.eventPublisher.notify('addressReverseGeocoded', address)));
}
}
AngularGoogleMapsBuilder.decorators = [
{ type: Injectable }
];
/** @nocollapse */
AngularGoogleMapsBuilder.ctorParameters = () => [
{ type: GoogleMapsFactory },
{ type: AngularGoogleMapsGeocoder },
{ type: EventPublisher }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class IconRegistry {
/**
* @param {?} iconRegistry
* @param {?} sanitizer
*/
constructor(iconRegistry, sanitizer) {
this.iconRegistry = iconRegistry;
this.sanitizer = sanitizer;
}
/**
* @param {?} iconName
* @param {?} resourceUrl
* @return {?}
*/
register(iconName, resourceUrl) {
this.iconRegistry.addSvgIcon(iconName, this.sanitizer.bypassSecurityTrustResourceUrl(resourceUrl));
}
}
IconRegistry.decorators = [
{ type: Injectable }
];
/** @nocollapse */
IconRegistry.ctorParameters = () => [
{ type: MatIconRegistry },
{ type: DomSanitizer }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class AngularGoogleMapsComponent {
/**
* @param {?} googleMapsFactory
* @param {?} googleMapsBuilder
* @param {?} googleMapsGeocoder
* @param {?} eventPublisher
* @param {?} iconRegistry
*/
constructor(googleMapsFactory, googleMapsBuilder, googleMapsGeocoder, eventPublisher, iconRegistry) {
this.googleMapsFactory = googleMapsFactory;
this.googleMapsBuilder = googleMapsBuilder;
this.googleMapsGeocoder = googleMapsGeocoder;
this.eventPublisher = eventPublisher;
this.iconRegistry = iconRegistry;
this.mapsText = mapsText;
this.address = '';
this.mapOptions = {
center: {
lat: 0,
lng: 0
},
mapTypeControlOptions: {
mapTypeIds: ['roadmap', 'satellite'],
position: this.googleMapsFactory.getGoogleMaps().ControlPosition.LEFT_BOTTOM
},
zoom: 16,
controlSize: 22,
fullscreenControl: false
};
this.markerOptions = {
position: {
lat: 0,
lng: 0
},
draggable: true,
animation: this.googleMapsFactory.getGoogleMaps().Animation.DROP
};
this.circleOptions = {
strokeColor: '#448aff',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#448aff',
fillOpacity: 0.35,
editable: true,
radius: 70
};
this.previousMarkerIcon = {
url: 'http://cdn.boldadmin.com.s3-website-eu-west-1.amazonaws.com/previous-marker.png'
};
this.currentMarkerIcon = {
url: 'http://cdn.boldadmin.com.s3-website-eu-west-1.amazonaws.com/current-marker.png'
};
}
/**
* @return {?}
*/
ngOnInit() {
this.eventPublisher.subscribe('addressReverseGeocoded', (/**
* @param {?} address
* @return {?}
*/
(address) => this.address = address));
this.iconRegistry.register('expand', './assets/expand.svg');
this.iconRegistry.register('collapse', './assets/collapse.svg');
}
/**
* @return {?}
*/
ngOnDestroy() {
this.eventPublisher.unsubscribeAll('addressReverseGeocoded');
}
/**
* @param {?} focusLocation
* @return {?}
*/
createMapByLocation(focusLocation) {
this.googleMapsGeocoder.reverseGeocode(focusLocation.coordinates, (/**
* @param {?} address
* @return {?}
*/
(address) => this.address = address));
this.circleOptions.radius = focusLocation.radiusInMeters;
this.changeMapCenter(focusLocation.coordinates);
this.googleMapsBuilder
.createMap(this.mapOptions)
.addCenterMarker(this.markerOptions)
.addCircle(this.circleOptions)
.bindCircleToMarker()
.addSearchBox();
}
/**
* @param {?} address
* @return {?}
*/
createMapByAddress(address) {
this.googleMapsGeocoder.geocode(address, (/**
* @param {?} coordinates
* @return {?}
*/
(coordinates) => {
this.changeMapCenter(coordinates);
this.googleMapsBuilder
.createMap(this.mapOptions)
.addCenterMarker(this.markerOptions)
.addCircle(this.circleOptions)
.bindCircleToMarker()
.hideMarker()
.hideCircle()
.addSearchBox();
}));
}
/**
* @return {?}
*/
notifyMapResize() {
this.eventPublisher.notify('resizeMap');
}
/**
* @param {?} timestampCoordinatesList
* @param {?} name
* @return {?}
*/
addTravelPath(timestampCoordinatesList, name) {
timestampCoordinatesList.forEach((/**
* @param {?} timestampCoordinates
* @param {?} index
* @return {?}
*/
(timestampCoordinates, index) => {
/** @type {?} */
const icon = index === 0 ? this.currentMarkerIcon : this.previousMarkerIcon;
/** @type {?} */
const dateTime = utc(timestampCoordinates.timestamp).format('YYYY.MM.DD HH:mm');
this.googleMapsBuilder.addMarker({
position: this.googleMapsFactory.createLatLng(timestampCoordinates.coordinates),
title: `Name: ${name}, Time: ${dateTime}`,
icon: icon
});
}));
/** @type {?} */
const latLngs = timestampCoordinatesList.map((/**
* @param {?} value
* @return {?}
*/
value => this.googleMapsFactory.createLatLng(value.coordinates)));
this.addPolyline(latLngs, '#' + Math.random().toString(16).substr(2, 6));
}
/**
* @private
* @param {?} path
* @param {?} colorCode
* @return {?}
*/
addPolyline(path, colorCode) {
this.googleMapsBuilder.addPolyline({
geodesic: true,
strokeOpacity: 0.8,
strokeWeight: 1,
path: path,
strokeColor: colorCode
});
}
/**
* @private
* @param {?} coordinates
* @return {?}
*/
changeMapCenter(coordinates) {
this.mapOptions.center = { lat: coordinates.latitude, lng: coordinates.longitude };
}
}
AngularGoogleMapsComponent.decorators = [
{ type: Component, args: [{
selector: 'google-maps',
template: "<input id=\"search-input\" name=\"searchBox\" class=\"controls\" type=\"text\"\n placeholder=\"{{mapsText.searchBox}}\"\n [ngModelOptions]=\"{standalone: true}\"\n [(ngModel)]=\"address\"/>\n<mat-icon id=\"expand-icon\" class=\"resize-control\" svgIcon=\"expand\" (click)=\"notifyMapResize()\"></mat-icon>\n<mat-icon id=\"collapse-icon\" class=\"resize-control\" svgIcon=\"collapse\" (click)=\"notifyMapResize()\"></mat-icon>\n\n<div id=\"map\"></div>\n",
providers: [AngularGoogleMapsBuilder]
}] }
];
/** @nocollapse */
AngularGoogleMapsComponent.ctorParameters = () => [
{ type: GoogleMapsFactory },
{ type: AngularGoogleMapsBuilder },
{ type: AngularGoogleMapsGeocoder },
{ type: EventPublisher },
{ type: IconRegistry }
];
AngularGoogleMapsComponent.propDecorators = {
mapOptions: [{ type: Output }],
markerOptions: [{ type: Output }],
circleOptions: [{ type: Output }],
previousMarkerIcon: [{ type: Output }],
currentMarkerIcon: [{ type: Output }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class GoogleMapsLoader {
/**
* @param {?} googleMapsApiKey
* @return {?}
*/
static load(googleMapsApiKey) {
return Promise.resolve(GoogleMapsApi({ key: googleMapsApiKey, libraries: ['places'] }));
}
}
GoogleMapsLoader.decorators = [
{ type: Injectable }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class AngularGoogleMapsModule {
}
AngularGoogleMapsModule.decorators = [
{ type: NgModule, args: [{
declarations: [
AngularGoogleMapsComponent
],
imports: [
FormsModule,
MatIconModule
],
exports: [
AngularGoogleMapsComponent
],
providers: [
AngularGoogleMapsGeocoder,
GoogleMapsLoader,
GoogleMapsFactory,
IconRegistry
]
},] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class TimestampCoordinates {
/**
* @param {?} coordinates
* @param {?} timestamp
*/
constructor(coordinates, timestamp) {
this.coordinates = coordinates;
this.timestamp = timestamp;
}
}
export { AngularGoogleMapsComponent, AngularGoogleMapsModule, Coordinates, GoogleMapsLoader, Location, TimestampCoordinates, AngularGoogleMapsBuilder as ɵa, GoogleMapsFactory as ɵb, AngularGoogleMapsGeocoder as ɵc, IconRegistry as ɵd };
//# sourceMappingURL=boldadmin-angular-google-maps.js.map