react-google-maps and google event listeners - how

2019-08-01 20:12发布

In my app I'm using react-google-maps (v.6.x.x) to handle api for Google Maps. I'm using markers and infobox to show proper information. Infobox with enableEventPropagation set to true, propagates events to map layer through the infobox - what does that mean? When I have infobox - aka infowindow whe I click on it, and underneath is placed marker, this marker is 'clicked' in first place, and than any html element in infobox. If enableEventPropagation is false - nothing is propagated. So my question is - is there any possibility to add google event listener for react component, for example code:

let infobox = (<InfoBox
  onDomReady={() => props.infoBoxReady(infobox)}
  defaultPosition={new google.maps.LatLng(props.activeMarker.location[1], props.activeMarker.location[0])}
  options={{
    closeBoxURL: ``, enableEventPropagation: true, pane: 'mapPane',
    position: new google.maps.LatLng(props.activeMarker.location[1], props.activeMarker.location[0]),
    alignBottom: true,
    pixelOffset: new google.maps.Size(-120, 0)
  }}>

How I can use this code to use Google Event Listener

google.maps.event.addListener(infobox, 'domready', function ()

Im getting this kind errorenter image description here

Any clue, how can I set listener for it, or maybe there are other options to set listeners for google map - unfortunately I've to use this library and handle clicks on infobox

4条回答
ら.Afraid
2楼-- · 2019-08-01 20:52

Not sure if this helps because this is a different react google maps plugin, but the issue seems quite similar: https://github.com/fullstackreact/google-maps-react/issues/70

查看更多
欢心
3楼-- · 2019-08-01 21:00

The only way I was able to prevent clicks through to the map (stop propagation) and still be able to click items in the in InfoBox is by setting "enableEventPropagation: false" and then adding listeners for the items in the InfoBox on the "onDomReady" prop. This makes sure that the listeners are attached after the InfoBox is rendered. Not sure if thats the best solution, but it did work. Hope that helps someone.

<InfoBox
  defaultPosition={new LatLng(marker.position.lat, marker.position.lng)}
  onDomReady={
      () => {
          let closeButton = $('a.close');
          let someLink = $('a.info-box-profile');

          closeButton.on('click', () => {
              // do something with the click
          });

          someLink.on('click', () => {
              // do something with the click
          });
      }
  }
  options={{
      pixelOffset: new Size(-145, 30),
      closeBoxURL: '',
      enableEventPropagation: false,
      boxStyle: {
          overflow: "hidden",
          width: "320px",
      }
  }}>
查看更多
▲ chillily
4楼-- · 2019-08-01 21:08

You can access the listeners via props on the InfoBox component.

Check them out here: Github docs

You're already using one - onDomReady - there's also:

  onCloseClick: `closeclick`,
  onContentChanged: `content_changed`,
  onPositionChanged: `position_changed`,
  onZIndexChanged: `zindex_changed`,
查看更多
▲ chillily
5楼-- · 2019-08-01 21:09

I wrote this wrapper component that places a <Rectangle/> over the entire map to stop clicks being passed through to the map below. Whilst still allowing you to click things inside the <infoBox/>.

This allows enableEventPropagation to be set to true without creating problems. I then use mouseOver and mouseOut to control how the rectangle works. In my case I use clicking on the rectangle to close my <InfoBox/>. You could just as easily hide and show it.

/* global google */
/* eslint-disable jsx-a11y/no-static-element-interactions */

import React from 'react';
import PropTypes from 'prop-types';
import { Rectangle } from 'react-google-maps';
import GoogleInfoBox from 'react-google-maps/lib/components/addons/InfoBox';

const cardWidth = 235;
const boxShadow = 25; // space for outer shadow
const iconHeight = 2; // the actual height is 48px but we use 6px instead to hide the icon but keep it's shadow

class InfoBox extends React.Component {
  constructor(props) {
    super(props);
    this.closable = true;
  }

  onClose = () => {
    if (this.closable) this.props.onClose();
  }

  onHover = () => {
    this.closable = false;
  }

  onMouseOut = () => {
    this.closable = true;
  }

  render() {
    const { children, position, onClose, type } = this.props;

    return (
      <div className="info-box">
        <Rectangle
          options={{ fillColor: '#ffffff', fillOpacity: 0.7, zIndex: 100 }}
          bounds={{ north: 90, south: -90, east: 180, west: -180 }}
          onClick={this.onClose}
        />
        <GoogleInfoBox
          position={new google.maps.LatLng(position.lat, position.lng)}
          onCloseClick={onClose}
          options={{
            alignBottom: true,
            disableAutoPan: false,
            pixelOffset: new google.maps.Size(-(cardWidth / 2) - boxShadow, -iconHeight),
            maxWidth: width,
            isHidden: false,
            visible: true,
            pane: 'floatPane',
            enableEventPropagation: true,
          }}
        >
          <div
            onMouseOver={this.onHover}
            onFocus={this.onHover}
            onMouseOut={this.onMouseOut}
            onBlur={this.onMouseOut}
          >
            { children }
          </div>
        </GoogleInfoBox>
      </div>
    );
  }
}

InfoBox.propTypes = {
  children: PropTypes.element.isRequired,
  position: PropTypes.shape({
    lat: PropTypes.number.isRequired,
    lng: PropTypes.number.isRequired,
  }).isRequired,
  onClose: PropTypes.func,
  type: PropTypes.string,
};

export default InfoBox;
查看更多
登录 后发表回答