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

标签 javascript google-maps reactjs redux infobox

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

一切正常,显示效果很好。问题来自实际单击信息框。我可以通过将 enableEventPropagation 更改为 true 或 false 来使其以两种方式之一工作:

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

  2. enableEventPropagation = false:点击不会传递到 map ,但 React 组件中的所有点击事件都不起作用。没有选项卡,没有按钮:什么都没有。看起来不错,但根本不起作用。

这是我创建信息框并使用 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 树的事件传播,这意味着子组件不起作用!疯了!

似乎我剩下的唯一选择就是在信息框被渲染后以某种方式计算它的纬度/经度范围,然后依次禁用该区域中的所有标记,但我想避免这是一堆废话!

或者我的方法完全错误?

最佳答案

您可以尝试一些事情。

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

我无法使用普通标记重现您的问题,但可以使用默认添加的 POI 重现。为防止打开 InfoBox 后面的任何标记,您可以在 InfoBox 上的 enterleave 上创建一个监听器,它将设置一个 bool 值,并覆盖 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 事件开始绑定(bind)他们的点击。不要真的认为这是相关的,因为我真的不知道如何使用 React 做到这一点,但仍然值得注意。

关于javascript - 将 React 组件渲染到 GoogleMaps InfoBox - 停止点击,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43807586/

相关文章:

javascript - 不允许使用 Google map API 引荐来源网址

javascript - 使用 Redux 和 React 按顺序执行异步操作

javascript - CKEditor5 React组件-添加插件问题

javascript - 如何在 javascript 函数中调用 CGI 函数?

javascript - 比较 js 日期……现在是星期几?

javascript - 将下拉列表值传递给谷歌地图javascript

javascript - 如何在 React JS 中为 div 动态设置类名

javascript - 在 Angular 表达式中嵌套引号

javascript - 如果没有搜索结果则显示消息

javascript - 谷歌地图天空 API v3