You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
520 lines
21 KiB
520 lines
21 KiB
2 years ago
|
var markerWithLabel = (function (exports) {
|
||
|
'use strict';
|
||
|
|
||
|
/**
|
||
|
* Copyright 2020 Google LLC. All Rights Reserved.
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
/**
|
||
|
* Extends an object's prototype by another's.
|
||
|
*
|
||
|
* @param type1 The Type to be extended.
|
||
|
* @param type2 The Type to extend with.
|
||
|
* @ignore
|
||
|
*/
|
||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||
|
function extend(type1, type2) {
|
||
|
// eslint-disable-next-line prefer-const
|
||
|
for (let property in type2.prototype) {
|
||
|
type1.prototype[property] = type2.prototype[property];
|
||
|
}
|
||
|
}
|
||
|
function abortEvent(e) {
|
||
|
e = e || window.event;
|
||
|
if (e.stopPropagation) {
|
||
|
e.stopPropagation();
|
||
|
}
|
||
|
else {
|
||
|
e.cancelBubble = true;
|
||
|
}
|
||
|
if (e.preventDefault) {
|
||
|
e.preventDefault();
|
||
|
}
|
||
|
else {
|
||
|
e.returnValue = false;
|
||
|
}
|
||
|
}
|
||
|
function stopPropagation(e) {
|
||
|
e = e || window.event;
|
||
|
if (e.stopPropagation) {
|
||
|
e.stopPropagation();
|
||
|
}
|
||
|
else {
|
||
|
e.cancelBubble = true;
|
||
|
}
|
||
|
}
|
||
|
function omit(o, keys) {
|
||
|
const x = Object.assign({}, o);
|
||
|
keys.forEach((k) => delete x[k]);
|
||
|
return x;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Copyright 2019 Google LLC. All Rights Reserved.
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
/**
|
||
|
* @ignore
|
||
|
*/
|
||
|
class OverlayViewSafe {
|
||
|
constructor() {
|
||
|
extend(OverlayViewSafe, google.maps.OverlayView);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Copyright 2020 Google LLC. All Rights Reserved.
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
const BLOCK = "block";
|
||
|
const NONE = "none";
|
||
|
const ABSOLUTE = "absolute";
|
||
|
const CURSOR = "pointer";
|
||
|
const LABEL_CLASS = "marker-label";
|
||
|
const EVENT_CLASS = "marker-label-event";
|
||
|
const EVENT_DIV_OPACITY = "0.01";
|
||
|
class Label extends OverlayViewSafe {
|
||
|
constructor({ clickable = true, cursor = CURSOR, draggable = true, labelAnchor = new google.maps.Point(0, 0), labelClass = LABEL_CLASS, labelContent, position, opacity = 1, map, labelZIndexOffset = 1, visible = true, zIndex = 0, }) {
|
||
|
super();
|
||
|
this.createElements();
|
||
|
this.anchor = labelAnchor;
|
||
|
this.content = labelContent;
|
||
|
this.className = labelClass;
|
||
|
this.clickable = clickable;
|
||
|
this.cursor = cursor;
|
||
|
this.draggable = draggable;
|
||
|
if (position instanceof google.maps.LatLng) {
|
||
|
this.position = position;
|
||
|
}
|
||
|
else {
|
||
|
this.position = new google.maps.LatLng(position);
|
||
|
}
|
||
|
this.opacity = opacity;
|
||
|
this.visible = visible;
|
||
|
this.zIndex = zIndex;
|
||
|
this.zIndexOffset = labelZIndexOffset;
|
||
|
if (map) {
|
||
|
this.setMap(map);
|
||
|
}
|
||
|
}
|
||
|
get element() {
|
||
|
return this.labelDiv;
|
||
|
}
|
||
|
get content() {
|
||
|
return this.labelDiv.innerHTML;
|
||
|
}
|
||
|
set content(content) {
|
||
|
if (typeof content === "string") {
|
||
|
this.labelDiv.innerHTML = content;
|
||
|
this.eventDiv.innerHTML = content;
|
||
|
}
|
||
|
else {
|
||
|
this.labelDiv.innerHTML = "";
|
||
|
this.labelDiv.appendChild(content);
|
||
|
this.eventDiv.innerHTML = "";
|
||
|
this.eventDiv.appendChild(content.cloneNode(true));
|
||
|
}
|
||
|
}
|
||
|
/**
|
||
|
* Get the class of the label div elements.
|
||
|
*
|
||
|
* **Note**: This will always return the default `marker-label`.
|
||
|
*/
|
||
|
get className() {
|
||
|
return this.labelDiv.className;
|
||
|
}
|
||
|
/**
|
||
|
* Set the class of the label div elements.
|
||
|
*
|
||
|
* **Note**: The default `marker-label` will additionaly be added.
|
||
|
*/
|
||
|
set className(className) {
|
||
|
this.labelDiv.className = className;
|
||
|
this.labelDiv.classList.add(LABEL_CLASS);
|
||
|
this.eventDiv.className = className;
|
||
|
this.eventDiv.classList.add(EVENT_CLASS);
|
||
|
}
|
||
|
set cursor(cursor) {
|
||
|
this.hoverCursor = cursor;
|
||
|
if (this.isInteractive) {
|
||
|
this.eventDiv.style.cursor = cursor;
|
||
|
}
|
||
|
}
|
||
|
get cursor() {
|
||
|
return this.isInteractive ? this.hoverCursor : "inherit";
|
||
|
}
|
||
|
get isInteractive() {
|
||
|
return this.draggable || this.clickable;
|
||
|
}
|
||
|
set opacity(opacity) {
|
||
|
this.labelDiv.style.opacity = String(opacity);
|
||
|
}
|
||
|
set title(title) {
|
||
|
this.eventDiv.title = title;
|
||
|
}
|
||
|
set visible(visible) {
|
||
|
if (visible) {
|
||
|
this.labelDiv.style.display = BLOCK;
|
||
|
this.eventDiv.style.display = BLOCK;
|
||
|
}
|
||
|
else {
|
||
|
this.labelDiv.style.display = NONE;
|
||
|
this.eventDiv.style.display = NONE;
|
||
|
}
|
||
|
}
|
||
|
onAdd() {
|
||
|
this.getPanes().markerLayer.appendChild(this.labelDiv);
|
||
|
this.getPanes().overlayMouseTarget.appendChild(this.eventDiv);
|
||
|
}
|
||
|
draw() {
|
||
|
const coordinates = this.getProjection().fromLatLngToDivPixel(this.position);
|
||
|
const x = Math.round(coordinates.x + this.anchor.x);
|
||
|
const y = Math.round(coordinates.y + this.anchor.y);
|
||
|
this.labelDiv.style.left = `${x}px`;
|
||
|
this.labelDiv.style.top = `${y}px`;
|
||
|
this.eventDiv.style.left = this.labelDiv.style.left;
|
||
|
this.eventDiv.style.top = this.labelDiv.style.top;
|
||
|
// If zIndex is not defined, used vertical position on map.
|
||
|
const zIndex = (this.zIndex || Math.ceil(coordinates.y)) + this.zIndexOffset;
|
||
|
this.labelDiv.style.zIndex = String(zIndex);
|
||
|
this.eventDiv.style.zIndex = String(zIndex);
|
||
|
// If not interactive set display none on event div
|
||
|
this.eventDiv.style.display = this.isInteractive
|
||
|
? this.eventDiv.style.display
|
||
|
: NONE;
|
||
|
this.eventDiv.style.cursor = this.cursor;
|
||
|
}
|
||
|
addDomListener(event, handler) {
|
||
|
return google.maps.event.addDomListener(this.eventDiv, event, handler);
|
||
|
}
|
||
|
onRemove() {
|
||
|
this.labelDiv.parentNode.removeChild(this.labelDiv);
|
||
|
this.eventDiv.parentNode.removeChild(this.eventDiv);
|
||
|
}
|
||
|
createElements() {
|
||
|
this.labelDiv = document.createElement("div");
|
||
|
this.eventDiv = document.createElement("div");
|
||
|
// default class names
|
||
|
this.labelDiv.classList.add(LABEL_CLASS);
|
||
|
this.labelDiv.classList.add(EVENT_CLASS);
|
||
|
// default styles for both divs
|
||
|
this.labelDiv.style.position = ABSOLUTE;
|
||
|
this.eventDiv.style.position = ABSOLUTE;
|
||
|
// default styles for eventDiv
|
||
|
this.eventDiv.style.opacity = EVENT_DIV_OPACITY;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Copyright 2020 Google LLC. All Rights Reserved.
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
/**
|
||
|
* @ignore
|
||
|
*/
|
||
|
class MarkerSafe {
|
||
|
constructor(options) {
|
||
|
extend(MarkerSafe, google.maps.Marker);
|
||
|
google.maps.Marker.call(this, options);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Copyright 2020 Google LLC. All Rights Reserved.
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
const CLICK = "click";
|
||
|
const DBLCLICK = "dblclick";
|
||
|
const DRAG = "drag";
|
||
|
const DRAGEND = "dragend";
|
||
|
const DRAGSTART = "dragstart";
|
||
|
const MOUSEDOWN = "mousedown";
|
||
|
const MOUSEMOVE = "mousemove";
|
||
|
const MOUSEOVER = "mouseover";
|
||
|
const MOUSEOUT = "mouseout";
|
||
|
const MOUSEUP = "mouseup";
|
||
|
class MarkerWithLabel extends MarkerSafe {
|
||
|
constructor(options) {
|
||
|
// need to omit extended options to Marker class that collide with setters/getters
|
||
|
super(omit(options, [
|
||
|
"labelAnchor",
|
||
|
"labelZIndexOffset",
|
||
|
"labelClass",
|
||
|
"labelContent",
|
||
|
]));
|
||
|
this.isTouchScreen = false;
|
||
|
this.isDraggingLabel = false;
|
||
|
this.isMouseDownOnLabel = false;
|
||
|
this.shouldIgnoreClick = false;
|
||
|
this.label = new Label(Object.assign({}, options));
|
||
|
this.propertyListeners = [
|
||
|
google.maps.event.addListener(this, "clickable_changed", this.handleClickableOrDraggableChange),
|
||
|
google.maps.event.addListener(this, "cursor_changed", () => {
|
||
|
this.label.cursor = this.getCursor();
|
||
|
}),
|
||
|
google.maps.event.addListener(this, "draggable_changed", this.handleClickableOrDraggableChange),
|
||
|
google.maps.event.addListener(this, "position_changed", () => {
|
||
|
this.label.position = this.getPosition();
|
||
|
}),
|
||
|
google.maps.event.addListener(this, "opacity_changed", () => {
|
||
|
this.label.opacity = this.getOpacity();
|
||
|
}),
|
||
|
google.maps.event.addListener(this, "title_changed", () => {
|
||
|
this.label.title = this.getTitle();
|
||
|
}),
|
||
|
google.maps.event.addListener(this, "visible_changed", () => {
|
||
|
this.label.visible = this.getVisible();
|
||
|
}),
|
||
|
google.maps.event.addListener(this, "zindex_changed", () => {
|
||
|
this.label.zIndex = this.getZIndex();
|
||
|
this.label.draw();
|
||
|
}),
|
||
|
];
|
||
|
}
|
||
|
get isInteractive() {
|
||
|
return this.getClickable() || this.getDraggable();
|
||
|
}
|
||
|
/**
|
||
|
* Gets label element.
|
||
|
*/
|
||
|
get labelElement() {
|
||
|
return this.label.element;
|
||
|
}
|
||
|
/**
|
||
|
* Gets label `innerHTML`. See {@link Marker.labelElement} for
|
||
|
* accessing the HTMLElement instead.
|
||
|
*/
|
||
|
get labelContent() {
|
||
|
return this.label.content;
|
||
|
}
|
||
|
set labelContent(content) {
|
||
|
this.label.content = content;
|
||
|
}
|
||
|
get labelClass() {
|
||
|
return this.label.className;
|
||
|
}
|
||
|
set labelClass(className) {
|
||
|
this.label.className = className;
|
||
|
}
|
||
|
setMap(map) {
|
||
|
super.setMap(map);
|
||
|
setTimeout(() => {
|
||
|
this.label.setMap(map);
|
||
|
this.removeInteractiveListeners();
|
||
|
if (map) {
|
||
|
this.addInteractiveListeners();
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
handleClickableOrDraggableChange() {
|
||
|
this.label.clickable = this.getClickable();
|
||
|
this.label.draggable = this.getDraggable();
|
||
|
if (this.isInteractive) {
|
||
|
this.addInteractiveListeners();
|
||
|
}
|
||
|
else {
|
||
|
this.removeInteractiveListeners();
|
||
|
}
|
||
|
}
|
||
|
removeInteractiveListeners() {
|
||
|
if (this.interactiveListeners) {
|
||
|
this.interactiveListeners.forEach((l) => google.maps.event.removeListener(l));
|
||
|
this.interactiveListeners = null;
|
||
|
}
|
||
|
}
|
||
|
addInteractiveListeners() {
|
||
|
if (!this.interactiveListeners) {
|
||
|
// If the map is not set, do not set listeners
|
||
|
if (!this.getMap()) {
|
||
|
return;
|
||
|
}
|
||
|
this.interactiveListeners = [
|
||
|
this.label.addDomListener(MOUSEOVER, (e) => {
|
||
|
if (!this.isTouchScreen) {
|
||
|
google.maps.event.trigger(this, MOUSEOVER, {
|
||
|
latLng: this.getPosition(),
|
||
|
});
|
||
|
abortEvent(e);
|
||
|
}
|
||
|
}),
|
||
|
this.label.addDomListener(MOUSEOUT, (e) => {
|
||
|
if (!this.isTouchScreen) {
|
||
|
// wrap the mouseout event in a timeout to avoid the case where mouseup occurs out
|
||
|
if (this.mouseOutTimeout) {
|
||
|
clearTimeout(this.mouseOutTimeout);
|
||
|
}
|
||
|
if (this.isMouseDownOnLabel) {
|
||
|
this.mouseOutTimeout = setTimeout(() => {
|
||
|
if (this.isMouseDownOnLabel) {
|
||
|
this.isMouseDownOnLabel = false;
|
||
|
google.maps.event.trigger(this, MOUSEUP, {
|
||
|
latLng: this.getPosition(),
|
||
|
});
|
||
|
if (this.isDraggingLabel) {
|
||
|
this.isDraggingLabel = false;
|
||
|
this.shouldIgnoreClick = true;
|
||
|
google.maps.event.trigger(this, DRAGEND, {
|
||
|
latLng: this.getPosition(),
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
google.maps.event.trigger(this, MOUSEOUT, {
|
||
|
latLng: this.getPosition(),
|
||
|
});
|
||
|
}, 200);
|
||
|
}
|
||
|
else {
|
||
|
google.maps.event.trigger(this, MOUSEOUT, {
|
||
|
latLng: this.getPosition(),
|
||
|
});
|
||
|
}
|
||
|
abortEvent(e);
|
||
|
}
|
||
|
}),
|
||
|
this.label.addDomListener(MOUSEDOWN, (e) => {
|
||
|
this.isDraggingLabel = false;
|
||
|
this.isMouseDownOnLabel = true;
|
||
|
google.maps.event.trigger(this, MOUSEDOWN, {
|
||
|
latLng: this.getPosition(),
|
||
|
});
|
||
|
if (!this.isTouchScreen) {
|
||
|
abortEvent(e);
|
||
|
}
|
||
|
}),
|
||
|
this.label.addDomListener(MOUSEUP, (e) => {
|
||
|
const markerEvent = { latLng: this.getPosition() };
|
||
|
if (this.isMouseDownOnLabel) {
|
||
|
this.isMouseDownOnLabel = false;
|
||
|
google.maps.event.trigger(this, MOUSEUP, markerEvent);
|
||
|
if (this.isDraggingLabel) {
|
||
|
this.isDraggingLabel = false;
|
||
|
this.shouldIgnoreClick = true;
|
||
|
google.maps.event.trigger(this, DRAGEND, markerEvent);
|
||
|
}
|
||
|
if (!this.getDraggable()) {
|
||
|
abortEvent(e);
|
||
|
}
|
||
|
}
|
||
|
}),
|
||
|
this.label.addDomListener(CLICK, (e) => {
|
||
|
if (this.shouldIgnoreClick) {
|
||
|
this.shouldIgnoreClick = false;
|
||
|
}
|
||
|
else {
|
||
|
google.maps.event.trigger(this, CLICK, {
|
||
|
latLng: this.getPosition(),
|
||
|
});
|
||
|
}
|
||
|
abortEvent(e);
|
||
|
}),
|
||
|
this.label.addDomListener(DBLCLICK, (e) => {
|
||
|
google.maps.event.trigger(this, DBLCLICK, {
|
||
|
latLng: this.getPosition(),
|
||
|
});
|
||
|
abortEvent(e);
|
||
|
}),
|
||
|
google.maps.event.addListener(this.getMap(), MOUSEMOVE, (e) => {
|
||
|
if (this.isMouseDownOnLabel && this.getDraggable()) {
|
||
|
if (this.isDraggingLabel) {
|
||
|
// Adjust for offset
|
||
|
const position = new google.maps.LatLng(e.latLng.lat() - this.eventOffset.y, e.latLng.lng() - this.eventOffset.x);
|
||
|
// this.setPosition(position);
|
||
|
google.maps.event.trigger(this, DRAG, Object.assign(Object.assign({}, e), { latLng: position }));
|
||
|
}
|
||
|
else {
|
||
|
this.isDraggingLabel = true;
|
||
|
// Calculate and store event offset from marker position
|
||
|
this.eventOffset = new google.maps.Point(e.latLng.lng() - this.getPosition().lng(), e.latLng.lat() - this.getPosition().lat());
|
||
|
google.maps.event.trigger(this, DRAGSTART, Object.assign(Object.assign({}, e), { latLng: this.getPosition() }));
|
||
|
}
|
||
|
}
|
||
|
}),
|
||
|
google.maps.event.addListener(this, DRAGSTART, () => {
|
||
|
this.label.zIndex = 1000000;
|
||
|
}),
|
||
|
google.maps.event.addListener(this, DRAG, ({ latLng }) => {
|
||
|
this.setPosition(latLng);
|
||
|
}),
|
||
|
google.maps.event.addListener(this, DRAGEND, () => {
|
||
|
this.label.zIndex = this.getZIndex();
|
||
|
this.label.draw();
|
||
|
}),
|
||
|
// Prevent touch events from passing through the label DIV to the underlying map.
|
||
|
this.label.addDomListener("touchstart", (e) => {
|
||
|
this.isTouchScreen = true;
|
||
|
stopPropagation(e);
|
||
|
}),
|
||
|
this.label.addDomListener("touchmove", (e) => {
|
||
|
stopPropagation(e);
|
||
|
}),
|
||
|
this.label.addDomListener("touchend", (e) => {
|
||
|
stopPropagation(e);
|
||
|
}),
|
||
|
];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
exports.MarkerWithLabel = MarkerWithLabel;
|
||
|
|
||
|
Object.defineProperty(exports, '__esModule', { value: true });
|
||
|
|
||
|
return exports;
|
||
|
|
||
|
})({});
|