将React组件渲染为GoogleMaps信息框 - 停止点击通过

问题描述:

我在Google地图InfoBox中的React应用程序中遇到问题。我的目标是在Google Maps实例上打开一个空InfoBox,然后使用ReactDOM.render将我的组件放入其中。该组件包含一组选项卡,每个选项卡窗格在打开时都会通过redux和thunk进行API调用。将React组件渲染为GoogleMaps信息框 - 停止点击通过

这一切工作正常,它显示很好。问题来自实际点击InfoBox。我可以得到它以两种方式工作之一,通过改变enableEventPropagation是真的还是假的:

  1. enableEventPropagation =真:组件的工作原理,所有的标签和按钮,但是任何标记下我的信息框会如果我碰巧点击了InfoBox的右边部分,它会打开我的应用程序的状态和流程。

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

这里是我创造我的信息框,并渲染它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" /> 
    ); 
} 

我曾尝试以下解决方案:

  • 交换到Google地图叠加。完全相同的问题,实际上看InfoBox插件似乎InfoBox是OverLay的一个包装,它有助于消除其中的一些问题,但仍然认为它只是非交互式的。

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

看来我唯一的选择就是以某种方式计算信息框的纬度/经度范围一旦它被渲染,然后依次禁用是在该地区的所有标记,但是这是胡说八道的哈克负载我想避免!

或者,也许我完全错误的做法?

+0

你打算推出一个JS小提琴吗?我使用googlemaps叠加层创建了自定义信息框,这听起来与此类似。我没有遇到你描述的任何问题。如果没有看到更多信息,很难说是什么原因造成的。如果有使用css指针事件的解决方案,我确实徘徊? –

+0

类似于[this](http://stackoverflow.com/q/24374588/3125070)one and/or [this](http://stackoverflow.com/q/23544327/3125070)其中之一? –

有几件事你可以尝试。

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

我无法用正常标记重现您的问题,但能够使用默认添加的POIs。要防止InfoBox背后的任何标记打开,可以在InfoBox上的enterleave上创建一个侦听器,该侦听器将设置布尔值,并覆盖set方法InfoWindow以取消悬停时的默认行为。你仍然可以看到鼠标光标变化,但可以使用一些基本的CSS删除。

下面是一个例子,点击标记打开InfoxBox后,点击Sechelt Aquatic Center标记,你不应该能够做到这一点。

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>

我也看到在一些地方,人们有同一种问题,不得不等待信息框domready事件开始结合自己的点击。不要认为这是相关的,因为我不知道如何使用React来做到这一点,但仍值得注意。

+0

该死的,谢谢你的回答!总的来说,这只是我没有考虑过的一个。整个mouseenter和mouseleave都非常出色,我最终通过在信息框中听取这些事件解决了我的问题,然后在我的redux商店中设置了一个值,当点击某个标记时检查该值,并在我将鼠标悬停在某个标记上时间接禁用所有其他标记信息框。谢谢! –