diff --git a/examples/Container.js b/examples/Container.js
index f1ffa64d..78eac928 100644
--- a/examples/Container.js
+++ b/examples/Container.js
@@ -52,6 +52,7 @@ class Container extends Component {
+
{routes.map(route => (
+
);
}
}
diff --git a/examples/components/withCustomOverlay.js b/examples/components/withCustomOverlay.js
new file mode 100644
index 00000000..439170b5
--- /dev/null
+++ b/examples/components/withCustomOverlay.js
@@ -0,0 +1,32 @@
+import React, { useState, Fragment } from 'react';
+import Map from '../../src/index';
+import CustomOverlay from '../../src/components/CustomOverlay';
+import styles from './withCustomOverlay.module.css';
+
+const WithCustomOverlay = (props) => {
+ const [showOverlay, setShowOverlay] = useState(true);
+ if (!props.loaded) return Loading...
;
+
+ return (
+
+
+
+
+ );
+};
+
+export default WithCustomOverlay;
diff --git a/examples/components/withCustomOverlay.module.css b/examples/components/withCustomOverlay.module.css
new file mode 100644
index 00000000..0a918c94
--- /dev/null
+++ b/examples/components/withCustomOverlay.module.css
@@ -0,0 +1,13 @@
+.overlayContainer {
+ background-color: white;
+ padding: 20px;
+ border-radius: 10px;
+ transform: translate(-50%, -100%);
+}
+
+.button {
+ position: absolute;
+ bottom: 10px;
+ left: 10px;
+ z-index: 1;
+}
\ No newline at end of file
diff --git a/examples/index.js b/examples/index.js
index 672f4339..b7443407 100644
--- a/examples/index.js
+++ b/examples/index.js
@@ -21,6 +21,7 @@ import Polygon from './components/withPolygons';
import Polyline from './components/withPolylines';
import Rectangle from './components/withRectangle';
import CustomEvents from './components/resizeEvent';
+import CustomOverlay from './components/withCustomOverlay';
const routes = [
{
@@ -72,6 +73,11 @@ const routes = [
path: '/onResizeEvent',
name: 'Custom events',
component: CustomEvents
+ },
+ {
+ path: '/onCustomPopup',
+ name: 'Custom overlay',
+ component: CustomOverlay
}
];
diff --git a/examples/styles.module.css b/examples/styles.module.css
index dc14afda..813c1567 100644
--- a/examples/styles.module.css
+++ b/examples/styles.module.css
@@ -64,5 +64,12 @@ html, body {
order: 2;
position: relative;
min-height: 100%;
+ display: flex;
+ flex-direction: column;
+
+ .mapContainer {
+ flex: 1;
+ position: relative;
+ }
}
}
diff --git a/index.d.ts b/index.d.ts
index 9499bf60..fd1167ed 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -106,3 +106,16 @@ export interface IInfoWindowProps extends Partial
export class InfoWindow extends React.Component {
}
+
+
+export interface ICustomOverlayProps {
+ google?: typeof google
+ map?: google.maps.Map
+ position: google.maps.LatLng | google.maps.LatLngLiteral,
+ visible?: boolean,
+ passThroughMouseEvents?: boolean
+}
+
+export class CustomOverlay extends React.Component {
+
+}
\ No newline at end of file
diff --git a/src/components/CustomOverlay.js b/src/components/CustomOverlay.js
new file mode 100644
index 00000000..e2cf250c
--- /dev/null
+++ b/src/components/CustomOverlay.js
@@ -0,0 +1,128 @@
+import React, { useRef, useEffect, useState } from 'react';
+import PropTypes from 'prop-types';
+
+function createPopupClass() {
+ function Popup({ position, content, map, passThroughMouseEvents, onDraw }) {
+ this.position = position;
+ this.containerDiv = content;
+ this.onDraw = onDraw;
+ this.setMap(map);
+ if (!passThroughMouseEvents) {
+ google.maps.OverlayView.preventMapHitsAndGesturesFrom(this.containerDiv);
+ }
+ }
+
+ Popup.prototype = Object.create(google.maps.OverlayView.prototype);
+
+ Popup.prototype.show = function () {
+ this.containerDiv.style.visibility = 'visible';
+ };
+
+ Popup.prototype.hide = function () {
+ this.containerDiv.style.visibility = 'hidden';
+ };
+
+ Popup.prototype.onAdd = function () {
+ this.getPanes().floatPane.appendChild(this.containerDiv);
+ };
+
+ Popup.prototype.onRemove = function () {
+ if (this.containerDiv.parentElement) {
+ this.containerDiv.parentElement.removeChild(this.containerDiv);
+ }
+ };
+
+ Popup.prototype.draw = function () {
+ if (!this.position) {
+ return;
+ }
+ this.onDraw();
+ var divPosition = this.getProjection().fromLatLngToDivPixel(this.position);
+ var display =
+ Math.abs(divPosition.x) < 4000 && Math.abs(divPosition.y) < 4000
+ ? 'block'
+ : 'none';
+
+ if (display === 'block') {
+ this.containerDiv.style.left = divPosition.x + 'px';
+ this.containerDiv.style.top = divPosition.y + 'px';
+ }
+ if (this.containerDiv.style.display !== display) {
+ this.containerDiv.style.display = display;
+ }
+ };
+
+ return Popup;
+}
+
+const asLatLng = (position) =>
+ !position || position instanceof google.maps.LatLng
+ ? position
+ : new google.maps.LatLng(position.lat, position.lng);
+
+export const CustomOverlay = ({
+ map,
+ position,
+ children,
+ visible,
+ className,
+ passThroughMouseEvents
+}) => {
+ const [hasDrawn, setHasDrawn] = useState(false);
+ const containerRef = useRef(null);
+ const popoverRef = useRef(null);
+
+ useEffect(() => {
+ if (map) {
+ const Popup = createPopupClass();
+ popoverRef.current = new Popup({
+ position: asLatLng(position),
+ content: containerRef.current,
+ map,
+ passThroughMouseEvents,
+ onDraw: () => setHasDrawn(true)
+ });
+ }
+ }, [map]);
+
+ useEffect(() => {
+ const popover = popoverRef.current;
+ if (popover) {
+ popover.position = asLatLng(position);
+ popover.draw();
+ }
+ }, [position]);
+
+ useEffect(() => {
+ const popover = popoverRef.current;
+ if (popover) {
+ visible ? popover.show() : popover.hide();
+ }
+ }, [visible]);
+
+ const display = hasDrawn ? 'block' : 'none';
+ return (
+
+ {visible && children}
+
+ );
+};
+
+CustomOverlay.propTypes = {
+ className: PropTypes.string,
+ children: PropTypes.node.isRequired,
+ map: PropTypes.object,
+ position: PropTypes.object,
+ visible: PropTypes.bool,
+ passThroughMouseEvents: PropTypes.bool
+};
+
+CustomOverlay.defaultProps = {
+ visible: true
+};
+
+export default CustomOverlay;
diff --git a/src/index.js b/src/index.js
index edd3abec..8d9141b9 100644
--- a/src/index.js
+++ b/src/index.js
@@ -50,6 +50,7 @@ export {Polygon} from './components/Polygon';
export {Polyline} from './components/Polyline';
export {Circle} from './components/Circle';
export {Rectangle} from './components/Rectangle';
+export {CustomOverlay} from './components/CustomOverlay';
export class Map extends React.Component {
constructor(props) {