193 lines
24 KiB
JavaScript
193 lines
24 KiB
JavaScript
|
/**
|
||
|
* @license
|
||
|
* Copyright Google LLC All Rights Reserved.
|
||
|
*
|
||
|
* Use of this source code is governed by an MIT-style license that can be
|
||
|
* found in the LICENSE file at https://angular.io/license
|
||
|
*/
|
||
|
// Workaround for: https://github.com/bazelbuild/rules_nodejs/issues/1265
|
||
|
/// <reference types="google.maps" preserve="true" />
|
||
|
import { Directive, EventEmitter, Input, NgZone, Output, inject, } from '@angular/core';
|
||
|
import { BehaviorSubject, Observable, Subject } from 'rxjs';
|
||
|
import { takeUntil } from 'rxjs/operators';
|
||
|
import { GoogleMap } from '../google-map/google-map';
|
||
|
import { MapEventManager } from '../map-event-manager';
|
||
|
import * as i0 from "@angular/core";
|
||
|
import * as i1 from "../google-map/google-map";
|
||
|
/**
|
||
|
* Angular component that renders a Google Maps Ground Overlay via the Google Maps JavaScript API.
|
||
|
*
|
||
|
* See developers.google.com/maps/documentation/javascript/reference/image-overlay#GroundOverlay
|
||
|
*/
|
||
|
export class MapGroundOverlay {
|
||
|
/** URL of the image that will be shown in the overlay. */
|
||
|
set url(url) {
|
||
|
this._url.next(url);
|
||
|
}
|
||
|
/** Bounds for the overlay. */
|
||
|
get bounds() {
|
||
|
return this._bounds.value;
|
||
|
}
|
||
|
set bounds(bounds) {
|
||
|
this._bounds.next(bounds);
|
||
|
}
|
||
|
/** Opacity of the overlay. */
|
||
|
set opacity(opacity) {
|
||
|
this._opacity.next(opacity);
|
||
|
}
|
||
|
constructor(_map, _ngZone) {
|
||
|
this._map = _map;
|
||
|
this._ngZone = _ngZone;
|
||
|
this._eventManager = new MapEventManager(inject(NgZone));
|
||
|
this._opacity = new BehaviorSubject(1);
|
||
|
this._url = new BehaviorSubject('');
|
||
|
this._bounds = new BehaviorSubject(undefined);
|
||
|
this._destroyed = new Subject();
|
||
|
/** Whether the overlay is clickable */
|
||
|
this.clickable = false;
|
||
|
/**
|
||
|
* See
|
||
|
* developers.google.com/maps/documentation/javascript/reference/image-overlay#GroundOverlay.click
|
||
|
*/
|
||
|
this.mapClick = this._eventManager.getLazyEmitter('click');
|
||
|
/**
|
||
|
* See
|
||
|
* developers.google.com/maps/documentation/javascript/reference/image-overlay
|
||
|
* #GroundOverlay.dblclick
|
||
|
*/
|
||
|
this.mapDblclick = this._eventManager.getLazyEmitter('dblclick');
|
||
|
/** Event emitted when the ground overlay is initialized. */
|
||
|
this.groundOverlayInitialized = new EventEmitter();
|
||
|
}
|
||
|
ngOnInit() {
|
||
|
if (this._map._isBrowser) {
|
||
|
// The ground overlay setup is slightly different from the other Google Maps objects in that
|
||
|
// we have to recreate the `GroundOverlay` object whenever the bounds change, because
|
||
|
// Google Maps doesn't provide an API to update the bounds of an existing overlay.
|
||
|
this._bounds.pipe(takeUntil(this._destroyed)).subscribe(bounds => {
|
||
|
if (this.groundOverlay) {
|
||
|
this.groundOverlay.setMap(null);
|
||
|
this.groundOverlay = undefined;
|
||
|
}
|
||
|
if (!bounds) {
|
||
|
return;
|
||
|
}
|
||
|
if (google.maps.GroundOverlay && this._map.googleMap) {
|
||
|
this._initialize(this._map.googleMap, google.maps.GroundOverlay, bounds);
|
||
|
}
|
||
|
else {
|
||
|
this._ngZone.runOutsideAngular(() => {
|
||
|
Promise.all([this._map._resolveMap(), google.maps.importLibrary('maps')]).then(([map, lib]) => {
|
||
|
this._initialize(map, lib.GroundOverlay, bounds);
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
_initialize(map, overlayConstructor, bounds) {
|
||
|
// Create the object outside the zone so its events don't trigger change detection.
|
||
|
// We'll bring it back in inside the `MapEventManager` only for the events that the
|
||
|
// user has subscribed to.
|
||
|
this._ngZone.runOutsideAngular(() => {
|
||
|
this.groundOverlay = new overlayConstructor(this._url.getValue(), bounds, {
|
||
|
clickable: this.clickable,
|
||
|
opacity: this._opacity.value,
|
||
|
});
|
||
|
this._assertInitialized();
|
||
|
this.groundOverlay.setMap(map);
|
||
|
this._eventManager.setTarget(this.groundOverlay);
|
||
|
this.groundOverlayInitialized.emit(this.groundOverlay);
|
||
|
// We only need to set up the watchers once.
|
||
|
if (!this._hasWatchers) {
|
||
|
this._hasWatchers = true;
|
||
|
this._watchForOpacityChanges();
|
||
|
this._watchForUrlChanges();
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
ngOnDestroy() {
|
||
|
this._eventManager.destroy();
|
||
|
this._destroyed.next();
|
||
|
this._destroyed.complete();
|
||
|
this.groundOverlay?.setMap(null);
|
||
|
}
|
||
|
/**
|
||
|
* See
|
||
|
* developers.google.com/maps/documentation/javascript/reference/image-overlay
|
||
|
* #GroundOverlay.getBounds
|
||
|
*/
|
||
|
getBounds() {
|
||
|
this._assertInitialized();
|
||
|
return this.groundOverlay.getBounds();
|
||
|
}
|
||
|
/**
|
||
|
* See
|
||
|
* developers.google.com/maps/documentation/javascript/reference/image-overlay
|
||
|
* #GroundOverlay.getOpacity
|
||
|
*/
|
||
|
getOpacity() {
|
||
|
this._assertInitialized();
|
||
|
return this.groundOverlay.getOpacity();
|
||
|
}
|
||
|
/**
|
||
|
* See
|
||
|
* developers.google.com/maps/documentation/javascript/reference/image-overlay
|
||
|
* #GroundOverlay.getUrl
|
||
|
*/
|
||
|
getUrl() {
|
||
|
this._assertInitialized();
|
||
|
return this.groundOverlay.getUrl();
|
||
|
}
|
||
|
_watchForOpacityChanges() {
|
||
|
this._opacity.pipe(takeUntil(this._destroyed)).subscribe(opacity => {
|
||
|
if (opacity != null) {
|
||
|
this.groundOverlay?.setOpacity(opacity);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
_watchForUrlChanges() {
|
||
|
this._url.pipe(takeUntil(this._destroyed)).subscribe(url => {
|
||
|
const overlay = this.groundOverlay;
|
||
|
if (overlay) {
|
||
|
overlay.set('url', url);
|
||
|
// Google Maps only redraws the overlay if we re-set the map.
|
||
|
overlay.setMap(null);
|
||
|
overlay.setMap(this._map.googleMap);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
_assertInitialized() {
|
||
|
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
||
|
if (!this.groundOverlay) {
|
||
|
throw Error('Cannot interact with a Google Map GroundOverlay before it has been initialized. ' +
|
||
|
'Please wait for the GroundOverlay to load before trying to interact with it.');
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0-next.2", ngImport: i0, type: MapGroundOverlay, deps: [{ token: i1.GoogleMap }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive }); }
|
||
|
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.0-next.2", type: MapGroundOverlay, isStandalone: true, selector: "map-ground-overlay", inputs: { url: "url", bounds: "bounds", clickable: "clickable", opacity: "opacity" }, outputs: { mapClick: "mapClick", mapDblclick: "mapDblclick", groundOverlayInitialized: "groundOverlayInitialized" }, exportAs: ["mapGroundOverlay"], ngImport: i0 }); }
|
||
|
}
|
||
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0-next.2", ngImport: i0, type: MapGroundOverlay, decorators: [{
|
||
|
type: Directive,
|
||
|
args: [{
|
||
|
selector: 'map-ground-overlay',
|
||
|
exportAs: 'mapGroundOverlay',
|
||
|
standalone: true,
|
||
|
}]
|
||
|
}], ctorParameters: () => [{ type: i1.GoogleMap }, { type: i0.NgZone }], propDecorators: { url: [{
|
||
|
type: Input
|
||
|
}], bounds: [{
|
||
|
type: Input
|
||
|
}], clickable: [{
|
||
|
type: Input
|
||
|
}], opacity: [{
|
||
|
type: Input
|
||
|
}], mapClick: [{
|
||
|
type: Output
|
||
|
}], mapDblclick: [{
|
||
|
type: Output
|
||
|
}], groundOverlayInitialized: [{
|
||
|
type: Output
|
||
|
}] } });
|
||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFwLWdyb3VuZC1vdmVybGF5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2dvb2dsZS1tYXBzL21hcC1ncm91bmQtb3ZlcmxheS9tYXAtZ3JvdW5kLW92ZXJsYXkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBRUgseUVBQXlFO0FBQ3pFLHFEQUFxRDtBQUVyRCxPQUFPLEVBQ0wsU0FBUyxFQUNULFlBQVksRUFDWixLQUFLLEVBQ0wsTUFBTSxFQUdOLE1BQU0sRUFDTixNQUFNLEdBQ1AsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFDLGVBQWUsRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBQzFELE9BQU8sRUFBQyxTQUFTLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUV6QyxPQUFPLEVBQUMsU0FBUyxFQUFDLE1BQU0sMEJBQTBCLENBQUM7QUFDbkQsT0FBTyxFQUFDLGVBQWUsRUFBQyxNQUFNLHNCQUFzQixDQUFDOzs7QUFFckQ7Ozs7R0FJRztBQU1ILE1BQU0sT0FBTyxnQkFBZ0I7SUFrQjNCLDBEQUEwRDtJQUMxRCxJQUNJLEdBQUcsQ0FBQyxHQUFXO1FBQ2pCLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3RCLENBQUM7SUFFRCw4QkFBOEI7SUFDOUIsSUFDSSxNQUFNO1FBQ1IsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQU0sQ0FBQztJQUM3QixDQUFDO0lBQ0QsSUFBSSxNQUFNLENBQUMsTUFBa0U7UUFDM0UsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDNUIsQ0FBQztJQUtELDhCQUE4QjtJQUM5QixJQUNJLE9BQU8sQ0FBQyxPQUFlO1FBQ3pCLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzlCLENBQUM7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
|