防止谷歌覆盖/ infowindow允许点击下面的标记 [英] Prevent google overlay/infowindow from allowing clicks through to markers underneath

查看:104
本文介绍了防止谷歌覆盖/ infowindow允许点击下面的标记的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图制作一些自定义的Google地图信息窗口,但我遇到了自定义信息窗口下方的标记可通过通过信息窗口进行点击的问题。



以下是一个示例(基本上直接从谷歌示例这里

 < html> 
< head>
< meta name =viewportcontent =initial-scale = 1.0,user-scalable = no/>
< meta http-equiv =content-typecontent =text / html; charset = UTF-8/>
< title> Google Maps JavaScript API v3示例:信息窗口自定义< / title>
< script type =text / javascriptsrc =http://maps.google.com/maps/api/js?sensor=false>< / script>
< script type =text / javascript>

/ * InfoBox就像一个信息窗口,但它在标记下显示
*,打开速度更快,并且具有灵活的样式。
* @param {GLatLng} latlng将位置栏放置在
* @param {Map}地图上显示此InfoBox的地图。
* @param {Object} opts通过配置选项 - 内容,
* offsetVertical,offsetHorizo​​ntal,className,height,width
* /
函数InfoBox(opts){
google.maps.OverlayView.call(this);
this.latlng_ = opts.latlng;
this.map_ = opts.map;
this.offsetVertical_ = -195;
this.offsetHorizo​​ntal_ = 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);
});

//一旦这个OverlayView的属性被初始化,将它的地图设置为
//,以便我们可以显示它。这将触发调用panes_changed和
//绘制。
this.setMap(this.map_);
}

/ * InfoBox从Google Maps API扩展GOverlay类
* /
InfoBox.prototype = new google.maps.OverlayView();
$ b $ *创建代表这个InfoBox的DIV
* /
InfoBox.prototype.remove = function(){
if(this.div_){
this.div_.parentNode.removeChild(this.div_);
this.div_ = null;
}
};

/ *根据当前投影和缩放级别重绘条形图
* /
InfoBox.prototype.draw = function(){
//创建元素如果它不存在。
this.createElement();
if(!this.div_)return;

//计算我们边界的两个对角的DIV坐标到
//获得我们的Bar的大小和位置
var pixPosition = this.getProjection()。fromLatLngToDivPixel (this.latlng_);
if(!pixPosition)return;

//现在根据边界的DIV坐标定位我们的DIV
this.div_.style.width = this.width_ +px;
this.div_.style.left =(pixPosition.x + this.offsetHorizo​​ntal_)+px;
this.div_.style.height = this.height_ +px;
this.div_.style.top =(pixPosition.y + this.offsetVertical_)+px;
this.div_.style.display ='block';
};

/ *在floatPane中创建表示此InfoBox的DIV。如果通过调用getPanes检索的窗格
*对象为null,则从
* DOM中删除该元素。如果div存在,但其父不是floatPane,请将div
*移动到新窗格。
*从平局中调用。或者,这可以在
* a panes_changed事件中专门调用。
* /
InfoBox.prototype.createElement = function(){
var panes = this.getPanes();
var div = this.div_;
if(!div){
//这不处理变化的窗格。您可以将地图设置为空和
//然后重置地图以移动div。
div = this.div_ = document.createElement(div);
div.style.border =0px none;
div.style.position =绝对;
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 =指针;
closeImg.src =http://gmaps-samples.googlecode.com/svn/trunk/images/closebigger.gif;
topDiv.appendChild(closeImg);

函数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){
//窗格已经改变。移动div。
div.parentNode.removeChild(div);
panes.floatPane.appendChild(div);
} else {
//窗格没有改变,所以不需要创建或移动div。
}
}

/ *平铺地图以适合信息框。
* /
InfoBox.prototype.panMap = 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 = 初始化() >
< div id =map_canvasstyle =width:100%; height:100%>< / div>
< / body>
< / html>

你可以看到我正在制作两个标记,一个在另一个的东北。点击底部的标记,然后观察其他标记是如何通过标记点击的(右'W'附近)。



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



这是使用api v3 btw。



有些东西像这样(这里转录没有测试我的coffeescript所以...)

  //全部在google.maps.OverlayView子类中。 

...
this.listeners = new Array(); //保存侦听器以后解除绑定
...
this.cancelEvents = function(){
events = ['mousedown','mousemove','mouseover',
' mouseout','mousewheel',
'DOMMouseScroll','touchstart','touchend',
'touchmove','dblclick','contextmenu'];
//请注意,如果您想要点击dom中的链接,请勿禁用点击。 (var i = 0; i< events.length; i ++){$ b $}我们在这里禁用的一些东西可能会影响用户如何与弹出窗口交互(双击以选择文本等) b 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(){
//建立你的html弹出框
var html_code =...;
//获取dom元素的简单方法,但如果只有它的唯一JQ
this.popup_dom_element = $(html_code);
this.cancelEvents();

$ b $ this.onRemove = function(){
//你有任何其他的移除代码
...
for(var i = 0 ; i< this.listeners.length; i ++){
//移除我们的事件监听器
google.maps.event.removeListener(this.listeners [i]);
}
}


I'm trying to make some custom Google maps info windows, but I'm getting the issue where markers underneath my custom info window is clickable through the info window.

Here's an example (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>

You can see I'm making two markers, one just to the north east of the other. Click the bottom one then observe how the other marker is clickable through the marker (right near the 'W').

How can I fix this?! I've tried altering the z-index but that didn't seem to help.

This is using api v3 btw.

解决方案

For posterity, you want to disable a bunch of events on the marker pop-up dom, this was the prescribed method, even though it feels like overkill. You could alternatively cycle through all the markers present apart from the one clicked and disable clicking on them (actually that's probably a better solution in hindsight). Depends on how many markers you have perhaps, I had a lot.

Something like this (transcribed here without testing from my coffeescript so...)

// 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]);
    }
}

这篇关于防止谷歌覆盖/ infowindow允许点击下面的标记的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆