@amin-karimi/agm-direction
Version:
Angular Google Maps direction
376 lines (370 loc) • 17.5 kB
JavaScript
import * as i0 from '@angular/core';
import { EventEmitter, Directive, Input, Output, NgModule } from '@angular/core';
import * as i1 from '@amin-karimi/agm-core';
class AgmDirection {
constructor(gmapsApi) {
this.gmapsApi = gmapsApi;
this.waypoints = [];
this.optimizeWaypoints = true;
this.provideRouteAlternatives = false;
this.avoidHighways = false;
this.avoidTolls = false;
this.avoidFerries = false;
// Remove or draw direction
this.visible = true;
// Direction change event handler
this.onChange = new EventEmitter();
// Direction response for the new request
this.onResponse = new EventEmitter();
// Send a custom infowindow
this.sendInfoWindow = new EventEmitter();
// Status of Directions Query (google.maps.DirectionsStatus.OVER_QUERY_LIMIT)
this.status = new EventEmitter();
// Marker drag event handler
this.originDrag = new EventEmitter();
this.destinationDrag = new EventEmitter();
this.waypointsMarker = [];
// Use for visible flag
this.isFirstChange = true;
}
ngOnInit() {
if (this.visible === true) {
this.directionDraw();
}
}
ngOnChanges(obj) {
/**
* When visible is false then remove the direction layer
*/
if (!this.visible) {
try {
this.removeMarkers();
this.removeDirections();
}
catch (e) { }
}
else {
if (this.isFirstChange) {
/**
* When visible is false at the first time
*/
if (typeof this.directionsRenderer === 'undefined') {
this.directionDraw();
}
this.isFirstChange = false;
return;
}
/**
* When renderOptions are not first change then reset the display
*/
if (typeof obj.renderOptions !== 'undefined') {
if (obj.renderOptions.firstChange === false) {
this.removeMarkers();
this.removeDirections();
}
}
this.directionDraw();
}
}
ngOnDestroy() {
this.destroyMarkers();
this.removeDirections();
}
/**
* This event is fired when the user creating or updating this direction
*/
directionDraw() {
this.gmapsApi.getNativeMap().then(_map => {
// const map = _map as unknown | google.maps.Map;
const map = _map;
if (typeof this.directionsRenderer === 'undefined') {
this.directionsRenderer = new google.maps.DirectionsRenderer(this.renderOptions);
// @ts-ignore
this.directionsRenderer.setMap(map);
this.directionsRenderer.addListener('directions_changed', () => {
this.onChange.emit(this.directionsRenderer.getDirections());
});
}
if (typeof this.directionsService === 'undefined') {
this.directionsService = new google.maps.DirectionsService();
}
if (typeof this.panel === 'undefined') {
// @ts-ignore
this.directionsRenderer.setPanel(null);
}
else {
this.directionsRenderer.setPanel(this.panel);
}
// Render exist direction
if (this.renderRoute) {
this.directionsRenderer.setDirections(this.renderRoute);
this.renderRoute = undefined;
}
else {
// Request new direction
this.directionsService.route({
origin: this.origin,
destination: this.destination,
travelMode: this.travelMode || google.maps.TravelMode.DRIVING,
transitOptions: this.transitOptions,
drivingOptions: this.drivingOptions,
waypoints: this.waypoints,
optimizeWaypoints: this.optimizeWaypoints,
provideRouteAlternatives: this.provideRouteAlternatives,
avoidHighways: this.avoidHighways,
avoidTolls: this.avoidTolls,
avoidFerries: this.avoidFerries,
unitSystem: this.unitSystem,
}, (response, status) => {
this.onResponse.emit(response);
// Emit Query Status
this.status.emit(status);
/**
* DirectionsStatus
* https://developers.google.com/maps/documentation/javascript/directions#DirectionsStatus
*/
switch (status) {
case google.maps.DirectionsStatus.OK:
this.directionsRenderer.setDirections(response);
/**
* Emit The DirectionsResult Object
* https://developers.google.com/maps/documentation/javascript/directions?hl=en#DirectionsResults
*/
// Custom Markers
if (typeof this.markerOptions !== 'undefined') {
this.destroyMarkers();
// Set custom markers
const _route = response.routes[0].legs[0];
try {
// Origin Marker
if (typeof this.markerOptions.origin !== 'undefined') {
this.markerOptions.origin.map = map;
this.markerOptions.origin.position = _route.start_location;
this.originMarker = this.setMarker(map, this.originMarker, this.markerOptions.origin, _route.start_address);
if (this.markerOptions.origin.draggable) {
this.originMarker.addListener('dragend', () => {
this.origin = this.originMarker.position;
this.directionDraw();
this.originDrag.emit(this.origin);
});
}
}
// Destination Marker
if (typeof this.markerOptions.destination !== 'undefined') {
this.markerOptions.destination.map = map;
this.markerOptions.destination.position = _route.end_location;
this.destinationMarker = this.setMarker(map, this.destinationMarker, this.markerOptions.destination, _route.end_address);
if (this.markerOptions.destination.draggable) {
this.destinationMarker.addListener('dragend', () => {
this.destination = this.destinationMarker.position;
this.directionDraw();
this.destinationDrag.emit(this.destination);
});
}
}
// Waypoints Marker
if (typeof this.markerOptions.waypoints !== 'undefined') {
this.waypoints.forEach((waypoint, index) => {
// If waypoints are not array then set all the same
if (!Array.isArray(this.markerOptions.waypoints)) {
this.markerOptions.waypoints.map = map;
this.markerOptions.waypoints.position = _route.via_waypoints[index];
this.waypointsMarker.push(this.setMarker(map, waypoint, this.markerOptions.waypoints, _route.via_waypoints[index]));
}
else {
this.markerOptions.waypoints[index].map = map;
this.markerOptions.waypoints[index].position = _route.via_waypoints[index];
this.waypointsMarker.push(this.setMarker(map, waypoint, this.markerOptions.waypoints[index], _route.via_waypoints[index]));
}
}); // End forEach
}
}
catch (err) {
console.error('MarkerOptions error.', err);
}
}
break;
case google.maps.DirectionsStatus.OVER_QUERY_LIMIT:
console.warn('The webpage has sent too many requests within the allowed time period.');
break;
default:
// console.warn(status);
break;
} // End switch
});
}
});
}
/**
* Custom Origin and Destination Icon
* @param map map
* @param marker marker
* @param markerOpts properties
* @param content marker's infowindow content
* @returns new marker
* @memberof AgmDirection
*/
setMarker(map, marker, markerOpts, content) {
if (typeof this.infoWindow === 'undefined') {
this.infoWindow = new google.maps.InfoWindow();
this.sendInfoWindow.emit(this.infoWindow);
}
marker = new google.maps.Marker(markerOpts);
// https://developers.google.com/maps/documentation/javascript/reference/marker?hl=zh-tw#MarkerOptions.clickable
if (marker.getClickable()) {
marker.addListener('click', () => {
const infowindoContent = typeof markerOpts.infoWindow === 'undefined' ? content : markerOpts.infoWindow;
this.infoWindow.setContent(infowindoContent);
this.infoWindow.open(map, marker);
});
}
return marker;
}
/**
* This event is fired when remove markers
*/
removeMarkers() {
if (typeof this.originMarker !== 'undefined') {
this.originMarker.setMap(null);
}
if (typeof this.destinationMarker !== 'undefined') {
this.destinationMarker.setMap(null);
}
this.waypointsMarker.forEach((w) => {
if (typeof w !== 'undefined') {
w.setMap(null);
}
});
}
/**
* This event is fired when remove directions
*/
removeDirections() {
if (this.directionsRenderer !== undefined) {
// @ts-ignore
this.directionsRenderer.setPanel(null);
this.directionsRenderer.setMap(null);
// @ts-ignore
this.directionsRenderer = undefined;
}
}
/**
* This event is fired when destroy markers
*/
destroyMarkers() {
// Remove origin markers
try {
if (typeof this.originMarker !== 'undefined') {
google.maps.event.clearListeners(this.originMarker, 'click');
if (this.markerOptions.origin.draggable) {
google.maps.event.clearListeners(this.originMarker, 'dragend');
}
}
if (typeof this.destinationMarker !== 'undefined') {
google.maps.event.clearListeners(this.destinationMarker, 'click');
if (this.markerOptions.origin.draggable) {
google.maps.event.clearListeners(this.destinationMarker, 'dragend');
}
}
this.waypointsMarker.forEach((w) => {
if (typeof w !== 'undefined') {
google.maps.event.clearListeners(w, 'click');
}
});
this.removeMarkers();
}
catch (err) {
console.error('Can not reset custom marker.', err);
}
}
}
AgmDirection.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AgmDirection, deps: [{ token: i1.GoogleMapsAPIWrapper }], target: i0.ɵɵFactoryTarget.Directive });
AgmDirection.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.12", type: AgmDirection, selector: "agm-direction", inputs: { origin: "origin", destination: "destination", travelMode: "travelMode", transitOptions: "transitOptions", drivingOptions: "drivingOptions", waypoints: "waypoints", optimizeWaypoints: "optimizeWaypoints", provideRouteAlternatives: "provideRouteAlternatives", avoidHighways: "avoidHighways", avoidTolls: "avoidTolls", avoidFerries: "avoidFerries", unitSystem: "unitSystem", renderOptions: "renderOptions", panel: "panel", markerOptions: "markerOptions", infoWindow: "infoWindow", visible: "visible", renderRoute: "renderRoute" }, outputs: { onChange: "onChange", onResponse: "onResponse", sendInfoWindow: "sendInfoWindow", status: "status", originDrag: "originDrag", destinationDrag: "destinationDrag" }, usesOnChanges: true, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AgmDirection, decorators: [{
type: Directive,
args: [{
selector: 'agm-direction',
}]
}], ctorParameters: function () { return [{ type: i1.GoogleMapsAPIWrapper }]; }, propDecorators: { origin: [{
type: Input
}], destination: [{
type: Input
}], travelMode: [{
type: Input
}], transitOptions: [{
type: Input
}], drivingOptions: [{
type: Input
}], waypoints: [{
type: Input
}], optimizeWaypoints: [{
type: Input
}], provideRouteAlternatives: [{
type: Input
}], avoidHighways: [{
type: Input
}], avoidTolls: [{
type: Input
}], avoidFerries: [{
type: Input
}], unitSystem: [{
type: Input
}], renderOptions: [{
type: Input
}], panel: [{
type: Input
}], markerOptions: [{
type: Input
}], infoWindow: [{
type: Input
}], visible: [{
type: Input
}], renderRoute: [{
type: Input
}], onChange: [{
type: Output
}], onResponse: [{
type: Output
}], sendInfoWindow: [{
type: Output
}], status: [{
type: Output
}], originDrag: [{
type: Output
}], destinationDrag: [{
type: Output
}] } });
class AgmDirectionModule {
static forRoot() {
return {
ngModule: AgmDirectionModule,
};
}
static forChild() {
return {
ngModule: AgmDirectionModule,
};
}
}
AgmDirectionModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AgmDirectionModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
AgmDirectionModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.2.12", ngImport: i0, type: AgmDirectionModule, declarations: [AgmDirection], exports: [AgmDirection] });
AgmDirectionModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AgmDirectionModule });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AgmDirectionModule, decorators: [{
type: NgModule,
args: [{
declarations: [
AgmDirection,
],
exports: [
AgmDirection,
]
}]
}] });
/*
* Public API Surface of agm-direction
*/
/**
* Generated bundle index. Do not edit.
*/
export { AgmDirection, AgmDirectionModule };
//# sourceMappingURL=agm-direction.mjs.map