【问题标题】:Prevent google overlay/infowindow from allowing clicks through to markers underneath防止谷歌覆盖/信息窗口允许点击下方的标记
【发布时间】:2011-11-22 21:25:55
【问题描述】:

我正在尝试制作一些自定义的 Google 地图信息窗口,但我遇到了这样一个问题,即我的自定义信息窗口下方的标记可以通过信息窗口点击。

这是一个例子 (basically straight from googles example here)

<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Google Maps JavaScript API v3 Example: Info Window Custom</title>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">

/* An InfoBox is like an info window, but it displays
 * under the marker, opens quicker, and has flexible styling.
 * @param {GLatLng} latlng Point to place bar at
 * @param {Map} map The map on which to display this InfoBox.
 * @param {Object} opts Passes configuration options - content,
 *   offsetVertical, offsetHorizontal, className, height, width
 */
function InfoBox(opts) {
  google.maps.OverlayView.call(this);
  this.latlng_ = opts.latlng;
  this.map_ = opts.map;
  this.offsetVertical_ = -195;
  this.offsetHorizontal_ = 0;
  this.height_ = 165;
  this.width_ = 266;

  var me = this;
  this.boundsChangedListener_ =
    google.maps.event.addListener(this.map_, "bounds_changed", function() {
      return me.panMap.apply(me);
    });

  // Once the properties of this OverlayView are initialized, set its map so
  // that we can display it.  This will trigger calls to panes_changed and
  // draw.
  this.setMap(this.map_);
}

/* InfoBox extends GOverlay class from the Google Maps API
 */
InfoBox.prototype = new google.maps.OverlayView();

/* Creates the DIV representing this InfoBox
 */
InfoBox.prototype.remove = function() {
  if (this.div_) {
    this.div_.parentNode.removeChild(this.div_);
    this.div_ = null;
  }
};

/* Redraw the Bar based on the current projection and zoom level
 */
InfoBox.prototype.draw = function() {
  // Creates the element if it doesn't exist already.
  this.createElement();
  if (!this.div_) return;

  // Calculate the DIV coordinates of two opposite corners of our bounds to
  // get the size and position of our Bar
  var pixPosition = this.getProjection().fromLatLngToDivPixel(this.latlng_);
  if (!pixPosition) return;

  // Now position our DIV based on the DIV coordinates of our bounds
  this.div_.style.width = this.width_ + "px";
  this.div_.style.left = (pixPosition.x + this.offsetHorizontal_) + "px";
  this.div_.style.height = this.height_ + "px";
  this.div_.style.top = (pixPosition.y + this.offsetVertical_) + "px";
  this.div_.style.display = 'block';
};

/* Creates the DIV representing this InfoBox in the floatPane.  If the panes
 * object, retrieved by calling getPanes, is null, remove the element from the
 * DOM.  If the div exists, but its parent is not the floatPane, move the div
 * to the new pane.
 * Called from within draw.  Alternatively, this can be called specifically on
 * a panes_changed event.
 */
InfoBox.prototype.createElement = function() {
  var panes = this.getPanes();
  var div = this.div_;
  if (!div) {
    // This does not handle changing panes.  You can set the map to be null and
    // then reset the map to move the div.
    div = this.div_ = document.createElement("div");
    div.style.border = "0px none";
    div.style.position = "absolute";
    div.style.background = "url('http://gmaps-samples.googlecode.com/svn/trunk/images/blueinfowindow.gif')";
    div.style.width = this.width_ + "px";
    div.style.height = this.height_ + "px";
    var contentDiv = document.createElement("div");
    contentDiv.style.padding = "30px"
    contentDiv.innerHTML = "<b>Hello World!</b>";

    var topDiv = document.createElement("div");
    topDiv.style.textAlign = "right";
    var closeImg = document.createElement("img");
    closeImg.style.width = "32px";
    closeImg.style.height = "32px";
    closeImg.style.cursor = "pointer";
    closeImg.src = "http://gmaps-samples.googlecode.com/svn/trunk/images/closebigger.gif";
    topDiv.appendChild(closeImg);

    function removeInfoBox(ib) {
      return function() {
        ib.setMap(null);
      };
    }

    google.maps.event.addDomListener(closeImg, 'click', removeInfoBox(this));

    div.appendChild(topDiv);
    div.appendChild(contentDiv);
    div.style.display = 'none';
    panes.floatPane.appendChild(div);
    this.panMap();
  } else if (div.parentNode != panes.floatPane) {
    // The panes have changed.  Move the div.
    div.parentNode.removeChild(div);
    panes.floatPane.appendChild(div);
  } else {
    // The panes have not changed, so no need to create or move the div.
  }
}

/* Pan the map to fit the InfoBox.
 */
InfoBox.prototype.panMap = function() {
};

function initialize() {
    var myOptions = {
      zoom: 8,
      center: new google.maps.LatLng(-33.397, 150.644),
      mapTypeId: google.maps.MapTypeId.ROADMAP,
      sensor: 'true'
    }
    var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);

    var marker = new google.maps.Marker({
        position: new google.maps.LatLng(-34, 150),
        map: map
    });
    google.maps.event.addListener(marker, "click", function(e) {
      var infoBox = new InfoBox({latlng: marker.getPosition(), map: map});
    });

    var m2 = new google.maps.Marker({
        position: new google.maps.LatLng(-33.5, 150.5),
        map: map
    });
    google.maps.event.addListener(m2, "click", function(e) {
      var infoBox = new InfoBox({latlng: m2.getPosition(), map: map});
    });

  }
</script>
</head>
<body style="margin:0px; padding:0px;" onload="initialize()">
  <div id="map_canvas" style="width:100%; height:100%"></div>
</body>
</html>

您可以看到我正在制作两个标记,一个位于另一个的东北部。单击底部的一个,然后观察另一个标记是如何通过该标记单击的(就在“W”附近)。

我该如何解决这个问题?!我已尝试更改 z-index,但这似乎没有帮助。

这是使用 api v3 顺便说一句。

【问题讨论】:

    标签: javascript google-maps google-maps-markers google-maps-styled


    【解决方案1】:

    尝试使用 MapPane overlayMouseTarget 而不是 floatPane。

    【讨论】:

    • 看其他答案,我觉得你的是唯一一个理解和解决实际问题的人。
    【解决方案2】:

    对于后代,您想禁用标记弹出 dom 上的一堆事件,这是规定的方法,即使感觉有点矫枉过正。您也可以循环浏览除单击的标记之外的所有标记并禁用单击它们(实际上,事后看来,这可能是一个更好的解决方案)。取决于你有多少标记,我有很多。

    类似 的东西(在此处转录,未经我的咖啡脚本测试,所以...)

    // All in a google.maps.OverlayView subclass.
    
    ...
    this.listeners = new Array(); // save listeners for unbinding later
    ...
    this.cancelEvents = function(){
        events = ['mousedown', 'mousemove', 'mouseover', 
                'mouseout', 'mouseup', 'mousewheel', 
                'DOMMouseScroll', 'touchstart', 'touchend', 
                'touchmove', 'dblclick', 'contextmenu'];
        // Note, don't disable 'click' if you want to be able to click links in the dom. Some things we're disabling here will can effect how your user might interact with the popup (double click to select text etc)
        for(var i = 0; i < events.length; i++){
            var event = events[i];
            this.listeners.push(
                google.maps.event.addDomListener(
                    this.popup_dom_element,
                    event,
                    function(ev){
                        e.cancelBubble = true;
                        if(e.stopPropagation){
                            e.stopPropagation();
                        }
                    }
                );
            );
        }
    }
    
    this.onAdd = function (){
        // build your html popup
        var html_code = "...";
        // easy way to get a dom element but probably over kill if its your only JQ
        this.popup_dom_element = $(html_code);
        this.cancelEvents();
    }
    
    this.onRemove = function(){
        // any other removal code you have
        ...
        for(var i = 0; i < this.listeners.length; i++){
            // remove our event listeners
            google.maps.event.removeListener(this.listeners[i]);
        }
    }
    

    【讨论】:

      【解决方案3】:

      如果您不希望人们能够点击标记,您可以致电marker.setClickable(false)

      【讨论】:

        【解决方案4】:

        我也遇到了同样的问题,其实很简单:/

        如果你使用的是 jquery 就设置

        $(div).bind("click",function(e) {
         return false;
        });
        

        在 InfoBox.prototype.createElement 函数中。这应该会有所帮助。

        干杯

        【讨论】:

        【解决方案5】:

        使用:

        google.maps.event.addDomListener

        而不是

        google.maps.event.addListener

        【讨论】:

        • 欢迎来到 StackOverflow。回答问题时,请尽量提供更多信息,以帮助向发布问题的人解释您的回答。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-07-26
        • 1970-01-01
        • 1970-01-01
        • 2011-08-21
        • 1970-01-01
        • 2023-03-21
        • 1970-01-01
        相关资源
        最近更新 更多