2012-06-02 93 views
14

我试图实现一个自定义的infoBubble,它具有打开到标记侧面的框,而不是在顶部的默认位置。结果比预期的更难。谷歌地图InfoBubble pixelOffset(从标记默认位置移动)

使用正常的infoWindow可以使用pixelOffset。看到这里的documentation

使用infoBubble这似乎并非如此。无论如何在infoBubble中使用pixelOffset,还是会做同样的事情?

我发现这很难搜索,如使用谷歌搜索,例如它没有返回任何相关结果Google Search

下面是我所有的资源我一直在使用。

  • infoBubble的示例here

  • 我的JavaScript设置地图和infoBubble here

现在我的JavaScript只是在案件jsfiddle链接坏了。

<script type="text/javascript"> 

    $(document).ready(function() { 
     init(); 
    }); 

    function init() { 

     //Setup the map 
     var googleMapOptions = { 
      center: new google.maps.LatLng(53.5167, -1.1333), 
      zoom: 13, 
      mapTypeId: google.maps.MapTypeId.ROADMAP 
     }; 

     //Start the map 
     var map = new google.maps.Map(document.getElementById("map_canvas"), 
     googleMapOptions); 

     var marker = new google.maps.Marker({ 
      position: new google.maps.LatLng(53.5267, -1.1333), 
      title: "Just a test" 
     }); 

     marker.setMap(map); 

     infoBubble = new InfoBubble({ 
      map: map, 
      content: '<div class="phoneytext">Some label</div>', 
      //position: new google.maps.LatLng(-35, 151), 
      shadowStyle: 1, 
      padding: '10px', 
      //backgroundColor: 'rgb(57,57,57)', 
      borderRadius: 5, 
      minWidth: 200, 
      arrowSize: 10, 
      borderWidth: 1, 
      borderColor: '#2c2c2c', 
      disableAutoPan: true, 
      hideCloseButton: false, 
      arrowPosition: 7, 
      backgroundClassName: 'phoney', 
      pixelOffset: new google.maps.Size(130, 120), 
      arrowStyle: 2 
     }); 
     infoBubble.open(map, marker); 

    } 
</script> 

更新

为了帮助回答这个问题之前,我有一个测试用例这里放在一起 。重要的行是38行,它应该指定标签的位置。

更新2

对于奖金被授予我需要看到infoBubble的示例定位从标记高于其默认位置移开。优选地在标记的右侧。

更新3

我已删除了更新1的测试用例,因为它是在我的旧公司的服务器托管。

+0

只是头脑风暴:如果您知道标记的位置:(LNG,LAT),然后(LNG + X,LAT)应该是泡的位置,正确的? – Gavriel

+0

这听起来像它可以工作是的 – Undefined

回答

9

看起来好像infoBubble库本身默认将气泡定位在它所绑定的标记上方。看看它们包含在库中的示例文件:http://code.google.com/p/google-maps-utility-library-v3/source/browse/trunk/infobubble/examples/example.html。特别注意从第99行到第122行以及使用这两个信息气泡。第一个是绑定到标记,但是第二个是独立的,因此如果你看到第106行,你可以定义一个位置。现在,基于这种理解,我在这个小提琴http://jsfiddle.net/pDFc3/中为你创造了一个例子。 infoBubble位于标记的右侧。

这很奇怪,因为infoBubble js库有一个setPosition函数(http://code.google.com/p/google-maps-utility-library-v3/source/browse/trunk/infobubble/src/infobubble.js?r=206)参见1027行。但由于某种原因,我等待DOM加载并尝试通过去infoBubble.setPosition(newLatLng);来改变位置,我不工作。相反,DOM装入后声明infoBubble.getPosition();会给我infoBubble绑定的标记的当前位置。所以setPosition()可能在js库中有一个bug,因为我相信它仍然在工作(我可能是错的,也许它只是越野车)。


我已经固定我的jsfiddle解决您的放大和缩小时,相应地(http://jsfiddle.net/pDFc3/)定位为infoBubble问题。首先让我解释一下逻辑。首先,Google Maps for road map类型的最大缩放级别为21 - 这个值对于卫星图像不一致,但用户可以使用的最大缩放比例为21.从21开始,每次缩小两点之间的差异可以是保持基于以下逻辑一致的“在屏幕上”:

consitent_screen_dist = initial_dist * (2^(21 - zoomlevel)) 

在我们的情况下,用于初始距离的合理值为0.00003度(标记和infoBubble之间)。因此,基于这样的逻辑,我添加了下面这段找到标记和infoBubble之间的初始纵向距离:

var newlong = marker.getPosition().lng() + (0.00003 * Math.pow(2, (21 - map.getZoom()))); 

同样,为了保证距离保持在每个变焦水平变化相一致,我们只是声明了一个新的经度我们听在变焦水平的变化:

google.maps.event.addListener(map, "zoom_changed", function() { 
     newlong = marker.getPosition().lng() + (0.00003 * Math.pow(2, (21 - map.getZoom()))); 
     infoBubble.setPosition(new google.maps.LatLng(marker.getPosition().lat(), newlong));     
    }); 

请记住,您可以使此代码更有效的通过声明为marker.getPosition和其他值是通过方法调用了变量。所以方法调用不会重复,并减慢代码的速度。

+0

以上的不同位置。这就是我正在寻找的,一个问题是,当放大和缩小标记时,标记会相对于标记移动,有时会完全隐藏它。你认为这是可以解决的问题吗? – Undefined

+0

的确如此,这是因为我们将infoBubble的位置与特定缩放级别的标记相关联。但是一旦你改变了缩放级别,标记和infoBubble之间的距离(两者的纬度/经度坐标之间的差异)不会改变。所以当你缩小时,差别非常小,你可以在标记上查看infoBubble。 –

+0

虽然有这个问题的解决方法,但我发现如果您不将infoBubble绑定到制造商那么您实际上可以使用infoBubble.setPosition(latlng)方法。这意味着我们可以使用google maps事件侦听器'zoom_changed'来侦听缩放更改,然后使用'getZoom()'函数确定如何根据缩放级别将infoBubble与标记相关联的类。我会用这个可能的修复更新我的jsfiddle,但可以根据这个原则进行实验。 –

1

不幸的是,在InfoBubble中没有像pixelOffset这样的选项。但是如果你只是想在你的例子中的标记上移动Bubble,你不应该在气泡初始化时设置地图参数。考虑下面的小提琴(我固定它你):

http://jsfiddle.net/ssrP9/5/


附:你的小提琴没有工作,因为你没有正确地添加资源 http://doc.jsfiddle.net/basic/introduction.html#add-resources

+0

忘了提及。我的答案是基于来源分析。 所以,如果你真的需要设置相对于标记的自定义偏移,有两种方法: 1.获取此库的源代码并添加必要的功能 2. [相当奇怪]将不可见标记与原始和开放气泡的必要偏移它。 –

+0

感谢那个jsfiddle我会在我的问题中加入这个。不幸的是,我正在寻找将InfoBubble放置在标记 – Undefined

1

我刚刚遇到完全相同的问题,但无法在任何地方找到答案。通过一点点的试验和错误,我解决了它。

您将使用Google JS文件作为“infoBubble”。进入这个文件,然后搜索...

InfoBubble.prototype.buildDom_ = function() { 

对于我来说,这是行203(但可能是以前的洗牌和编辑的结果)。

在该函数中,您会看到位置“绝对”声明。在新行中,您可以添加marginTop,marginRight,marginBottom和marginLeft。这将从默认位置推动气泡(这也取决于您的配置中的箭头位置声明)...

这是我的代码在气泡JS文件中调整,将气泡放置在标记顶部(由于设计特点)...

var bubble = this.bubble_ = document.createElement('DIV'); 
bubble.style['position'] = 'absolute'; 
bubble.style['marginTop'] = this.px(21); 
bubble.style['marginLeft'] = this.px(1); 
bubble.style['zIndex'] = this.baseZIndex_; 

希望有所帮助。

0

在InfoBubble buildDom功能,添加:

bubble.className = 'bubble-container'; 

现在,你必须为每个InfoBubble CSS类,你可以使用CSS保证金接班。

8

这是我的解决方案。

InfoBubble

更换

整个InfoBubble.prototype.draw方法

/* 
* Sets InfoBubble Position 
* */ 
InfoBubble.prototype.setBubbleOffset = function(xOffset, yOffset) { 
    this.bubbleOffsetX = parseInt(xOffset); 
    this.bubbleOffsetY = parseInt(yOffset); 
} 


/* 
* Gets InfoBubble Position 
* */ 
InfoBubble.prototype.getBubbleOffset = function() { 
    return { 
    x: this.bubbleOffsetX || 0, 
    y: this.bubbleOffsetY || 0 
    } 
} 

/** 
* Draw the InfoBubble 
* Implementing the OverlayView interface 
*/ 
InfoBubble.prototype.draw = function() { 
    var projection = this.getProjection(); 

    if (!projection) { 
    // The map projection is not ready yet so do nothing 
    return; 
    } 

    var latLng = /** @type {google.maps.LatLng} */ (this.get('position')); 

    if (!latLng) { 
    this.close(); 
    return; 
    } 

    var tabHeight = 0; 

    if (this.activeTab_) { 
    tabHeight = this.activeTab_.offsetHeight; 
    } 

    var anchorHeight = this.getAnchorHeight_(); 
    var arrowSize = this.getArrowSize_(); 
    var arrowPosition = this.getArrowPosition_(); 

    arrowPosition = arrowPosition/100; 

    var pos = projection.fromLatLngToDivPixel(latLng); 
    var width = this.contentContainer_.offsetWidth; 
    var height = this.bubble_.offsetHeight; 

    if (!width) { 
    return; 
    } 

    // Adjust for the height of the info bubble 
    var top = pos.y - (height + arrowSize) + this.getBubbleOffset().y; 

    if (anchorHeight) { 
    // If there is an anchor then include the height 
    top -= anchorHeight; 
    } 

    var left = pos.x - (width * arrowPosition) + this.getBubbleOffset().x; 

    this.bubble_.style['top'] = this.px(top); 
    this.bubble_.style['left'] = this.px(left); 

    var shadowStyle = parseInt(this.get('shadowStyle'), 10); 

    switch (shadowStyle) { 
    case 1: 
     // Shadow is behind 
     this.bubbleShadow_.style['top'] = this.px(top + tabHeight - 1); 
     this.bubbleShadow_.style['left'] = this.px(left); 
     this.bubbleShadow_.style['width'] = this.px(width); 
     this.bubbleShadow_.style['height'] = 
     this.px(this.contentContainer_.offsetHeight - arrowSize); 
     break; 
    case 2: 
     // Shadow is below 
     width = width * 0.8; 
     if (anchorHeight) { 
     this.bubbleShadow_.style['top'] = this.px(pos.y); 
     } else { 
     this.bubbleShadow_.style['top'] = this.px(pos.y + arrowSize); 
     } 
     this.bubbleShadow_.style['left'] = this.px(pos.x - width * arrowPosition); 

     this.bubbleShadow_.style['width'] = this.px(width); 
     this.bubbleShadow_.style['height'] = this.px(2); 
     break; 
    } 
}; 

,然后你可以通过

var infoBubble = new InfoBubble({ 
    map: map, 
    content: "My Content", 
    position: new google.maps.LatLng(1, 1), 
    shadowStyle: 1, 
    padding: 0, 
    backgroundColor: 'transparent', 
    borderRadius: 7, 
    arrowSize: 10, 
    borderWidth: 1, 
    borderColor: '#2c2c2c', 
    disableAutoPan: true, 
    hideCloseButton: true, 
    arrowPosition: 50, 
    backgroundClassName: 'infoBubbleBackground', 
    arrowStyle: 2 

}); 
使用

然后最后我们使用这种方法setBubbleOffset(x,y);设置InfoBubble位置

infoBubble.setBubbleOffset(0,-32); 
1

你也可以使用一个定义锚高度;

var anchorHeight = YOURNUMBER; 

线874 infobubble.js