将React组件渲染到GoogleMaps InfoBox中 - 停止点击

时间:2017-05-05 14:31:03

标签: javascript google-maps reactjs redux infobox

我在React应用程序中遇到谷歌地图InfoBox的问题。我的目标是在谷歌地图实例上打开一个空的InfoBox,然后使用ReactDOM.render将我的组件放入其中。该组件由一组选项卡组成,每个选项卡窗格通过redux和thunk在打开时进行API调用。

这一切都很好,它显示得很好。问题来自实际点击InfoBox。我可以通过将enableEventPropagation更改为true或false来使其以两种方式之一工作:

  1. enableEventPropagation = true:组件工作,所有选项卡和按钮,但如果我碰巧点击InfoBox的右侧部分,我的InfoBox下面的任何标记都将被打开,这完全打破了状态和流程我的申请。

  2. enableEventPropagation = false:点击不会传递到地图,但反应组件中的任何点击事件都不起作用。没有标签,没有按钮:没有。看起来很棒,但根本不起作用。

  3. 这是我创建InfoBox并使用ReactDOM呈现给它的代码:

    renderInfoBox() {
        let {map, google, infoBox} = this.props;
        let markerElement = MarkerElementService.getMarkerElement(infoBox.ui.markerId);
    
        this.infoBox = new this.infoBoxClass({
            content: this.refs.infoBoxHolder,
            enableEventPropagation: false,
            pixelOffset: new google.maps.Size(10, -275),
            maxWidth: 350,
            zIndex: 99999999,
            infoBoxClearance: new google.maps.Size(75, 75)
        });
    
        ReactDOM.render(
            <Provider store={AppStore}>
                <ThemeProvider theme={Theme}>
                    <InfoBoxComponent google={google} onClose={this.closeButtonClicked.bind(this)} />
                </ThemeProvider>
            </Provider>,
            this.refs.infoBoxHolder,
            () => {
                this.infoBox.open(map, markerElement);
            }
        );
    }
    
    render() {
        return (
            <div ref="infoBoxHolder" />
        );
    }
    

    我尝试了以下解决方案:

    • 交换到GoogleMaps OverLay。完全相同的问题,实际上看InfoBox插件似乎InfoBox是OverLay的包装器,它有助于消除其中的一些问题,但仍假设它只是非交互式的。

    • 在我的组件内部的各个点禁用事件传播,但效果是它禁用DOM树中的事件传播,而不是up,这意味着子组件不起作用!狂!

    似乎我唯一的选择是以某种方式计算InfoBox一旦被渲染后的Lat / Lng界限,然后依次禁用该区域中的所有标记,但这是我想要避免的一堆废话! / p>

    或许我的方法完全错误?

1 个答案:

答案 0 :(得分:2)

你可以尝试一些事情。

首先,如果您没有很多标记,则可以尝试将标记optimized标记设置为false。它会将它们渲染为单独的DOM元素,从而降低性能,但不会像您遇到的那样产生奇怪的行为。

我无法使用普通标记重现您的问题,但能够使用默认情况下添加的POI。为了防止InfoBox后面的任何标记打开,您可以在InfoBox上的enterleave上创建一个设置布尔值的侦听器,并覆盖set InfoWindow方法在您悬停时取消默认行为。您仍然可以看到鼠标光标发生变化,但可以使用一些基本的CSS删除它。

以下是一个示例,点击标记后点击Sechelt Aquatic Center标记打开InfoxBox,你应该无法做到。

function initialize () {

  let enableMarkers = true
  
  const set = google.maps.InfoWindow.prototype.set;
  google.maps.InfoWindow.prototype.set = function (key, val) {
    if (key === 'map') {
      if (!enableMarkers) {
        return
      }
    }
    set.apply(this, arguments)
  }

  const map = new google.maps.Map(document.getElementById('map'), {
    zoom: 15,
    center: new google.maps.LatLng(49.47216, -123.76307),
    mapTypeId: google.maps.MapTypeId.ROADMAP,
  })

  const marker = new google.maps.Marker({
    map,
    draggable: true,
    position: new google.maps.LatLng(49.47216, -123.76307),
    visible: true
  })

  const box = document.createElement('div')
  box.innerHTML = 'Hello <br> Hello <br> Hello'

  google.maps.event.addListener(marker, 'click', function (e) {
    if (!enableMarkers) { return }
    ib.open(map, this)
  })

  const ib = new InfoBox({
    content: box,
    zIndex: 10,
    pixelOffset: new google.maps.Size(-100, 0),
    boxStyle: { 
      background: 'white',
      padding: '5px',
      opacity: 0.75,
      width: '200px',
    },
    closeBoxMargin: '2px',
    closeBoxURL: 'https://www.google.com/intl/en_us/mapfiles/close.gif',
    isHidden: false,
    enableEventPropagation: true,
  })
  
  box.addEventListener('mouseenter', () => {
    enableMarkers = false
  })
  
  box.addEventListener('mouseleave', () => {
    enableMarkers = true
  })
}
<script src="https://maps.googleapis.com/maps/api/js?v=3&amp;sensor=false"></script>
<script src="https://rawgit.com/googlemaps/v3-utility-library/master/infobox/src/infobox.js"></script>

<body onload="initialize()">
  <div id="map" style="width: 100%; height: 200px"></div>
</body>

我也在一些地方看到人们遇到同样的问题,不得不等待InfoBox domready事件开始绑定他们的点击。不要认为这是相关的,因为我真的不知道如何使用React做到这一点,但仍然值得注意。