简体   繁体   English

Google Maps InfoBubble pixelOffset(从标记上方的默认位置移动)

[英]Google Maps InfoBubble pixelOffset (Moving from default position above marker)

I am trying to implement a custom infoBubble that has the box opening to the side of a marker rather than the default position of on top. 我正在尝试实现一个自定义的infoBubble,其中的框打开到标记的一侧而不是顶部的默认位置。 This has turned out to be harder than expected. 事实证明这比预期更难。

Using the normal infoWindow you can use pixelOffset. 使用普通的infoWindow,您可以使用pixelOffset。 See here for the documentation 请参阅此处获取文档

Using infoBubble this does not seem to be the case. 使用infoBubble似乎并非如此。 Is there anyway of using pixelOffset in an infoBubble, or something that will do the same thing? 无论如何在infoBubble中使用pixelOffset,还是会做同样的事情?

I have found this very difficult to search for, as using a google search such as this returns no relevant results Google Search 我发现这很难搜索,因为使用Google这样的搜索会返回Google搜索没有相关结果

Below is all my resources I have been using. 以下是我一直使用的所有资源。

  • Example of infoBubble here . 这里有infoBubble的例子。

  • My JavaScript to setup the map and infoBubble here . 在这里设置地图和infoBubble的JavaScript。

And now my javascript here just in-case the jsfiddle link is broken. 现在我的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>

Update 更新

To help with answering this question i have put together a test case here . 为了帮助回答这个问题,我 在这里 整理了一个测试用例。 The important lines are lines 38 & 39, which should specify where to position the label. 重要的是第38和39行,它们应指定标签的位置。

Update 2 更新2

For the bounty to be awarded i need to see an example of the infoBubble positioned away from its default position above the marker. 对于要奖励的赏金,我需要查看infoBubble远离其在标记上方的默认位置的示例。 Preferably to the right hand side of the marker. 优选地在标记的右手侧。

Update 3 更新3

I have removed the testcase from update 1 because it is hosted on my old company's servers. 我已从更新1中删除了测试用例,因为它托管在我旧公司的服务器上。

It seems as though the infoBubble library itself defaults to positioning the bubble above the marker it is bound to. 好像infoBubble库本身默认将气泡定位在它所绑定的标记之上。 Take a look at the sample file they included in the library: http://code.google.com/p/google-maps-utility-library-v3/source/browse/trunk/infobubble/examples/example.html . 请查看它们包含在库中的示例文件: http//code.google.com/p/google-maps-utility-library-v3/source/browse/trunk/infobubble/examples/example.html Specifically notice from line 99 to line 122 and the use of the two infobubbles. 具体请注意从第99行到第122行以及使用两个信息。 The first one is bound to the marker, however the second one is a stand-alone and thus if you see line 106, you can define a position to it. 第一个绑定到标记,但第二个是独立的,因此如果您看到第106行,则可以为其定义位置。 Now, based on this understanding I've created an example for you in this fiddle http://jsfiddle.net/pDFc3/ . 现在,基于这种理解,我在这个小提琴http://jsfiddle.net/pDFc3/中为你创造了一个例子。 The infoBubble is positioned to the right of the marker. infoBubble位于标记的右侧。

It's strange, because the infoBubble js library has a function for setPosition ( http://code.google.com/p/google-maps-utility-library-v3/source/browse/trunk/infobubble/src/infobubble.js?r=206 ) see Line 1027. But for some reason after I wait for the DOM to load and try to change the position by going infoBubble.setPosition(newLatLng); 这很奇怪,因为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);来改变位置infoBubble.setPosition(newLatLng); I doesn't work. 我不工作。 On the contrary, declaring infoBubble.getPosition(); 相反,声明infoBubble.getPosition(); after the DOM loads gives me the current position of the marker the infoBubble is bound to. 在DOM加载后,我将获得infoBubble绑定的标记的当前位置。 So setPosition() may have a bug in the js library, because I believe it is still being worked on (I could be wrong maybe it's just buggy). 所以setPosition()可能在js库中有一个错误,因为我相信它仍在处理(我可能错了,也许它只是错误)。


I've fixed my jsFiddle to solve your issue for when zooming in and out, and positioning the infoBubble accordingly ( http://jsfiddle.net/pDFc3/ ). 我已经修复了我的jsFiddle以解决你在放大和缩小时的问题,并相应地定位infoBubble( http://jsfiddle.net/pDFc3/ )。 Let me explain the logic first. 让我先解释一下逻辑。 Firstly, the maximum zoom level on Google Maps for road map type is 21 - this value is inconsistent for satellite imagery but the maximum zoom the user can go to is 21. From 21, each time you zoom out the differences between two points can be kept consistent "on screen" based on the following logic: 首先,Google地图上道路地图类型的最大缩放级别为21 - 此值与卫星图像不一致,但用户可以进行的最大缩放为21.从21开始,每次缩小两点之间的差异即可基于以下逻辑保持“在屏幕上”的一致性:

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

In our case, the reasonable value for initial distance was 0.00003 degrees (between marker and infoBubble). 在我们的例子中,初始距离的合理值是0.00003度(在marker和infoBubble之间)。 So, based on this logic I added the following piece to find the initial longitudinal distance between marker and infoBubble: 所以,基于这个逻辑,我添加了以下部分来找到marker和infoBubble之间的初始纵向距离:

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

Likewise, to ensure the distance stays consistent on each zoom level change we simply declare a new longitude as we listen for a change in the zoom level: 同样,为了确保距离在每个缩放级别更改时保持一致,我们只需在侦听缩放级别更改时声明新的经度:

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

Keep in mind you can make this code much more efficient by declaring variables for marker.getPosition and other values that are called through methods. 请记住,通过声明marker.getPosition的变量和通过方法调用的其他值,可以使此代码更有效。 So that the method calls aren't repeated and slow your code down. 这样就不会重复方法调用并减慢代码速度。

This is my solution. 这是我的解决方案。

In InfoBubble library InfoBubble库中

replace 更换

entire InfoBubble.prototype.draw method 整个InfoBubble.prototype.draw方法

with

/*
 * 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;
  }
};

and then you can use this by 然后你可以使用它

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

});

Then finally we have to use this method setBubbleOffset(x,y); 最后我们必须使用这个方法setBubbleOffset(x,y); to set InfoBubble position 设置InfoBubble位置

infoBubble.setBubbleOffset(0,-32);

Unfortunately there is no such option as pixelOffset in InfoBubble. 不幸的是,InfoBubble中没有pixelOffset这样的选项。 But if you just want to move up Bubble above the marker in your example you should not set map parameter at bubble initialization. 但是,如果您只想在示例中将Bubble上移到标记之上,则不应在气泡初始化时设置map参数。 Consider the following fiddle (i fixed it for you): 考虑以下小提琴(我为你修好):

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


PS Your fiddle didn't work because you hadnt added resources properly http://doc.jsfiddle.net/basic/introduction.html#add-resources PS你的小提琴没用,因为你没有正确添加资源http://doc.jsfiddle.net/basic/introduction.html#add-resources

I've just come across the exact same issue but couldn't find an answer anywhere. 我刚刚遇到了完全相同的问题但无法在任何地方找到答案。 Through a little trial and error I worked it out. 通过一些试验和错误,我解决了这个问题。

You'll be using the Google JS file for "infoBubble". 您将使用Google JS文件“infoBubble”。 Go into this file and search for... 进入此文件并搜索...

InfoBubble.prototype.buildDom_ = function() {

For me, this is on line 203 (but that could be the result of previous shuffling and edits). 对我来说,这是在第203行(但这可能是之前的改组和编辑的结果)。

Within that function you'll see the position "absolute" declaration. 在该函数中,您将看到“绝对”声明的位置。 On a new line, you can add marginTop, marginRight, marginBottom and marginLeft. 在新行上,您可以添加marginTop,marginRight,marginBottom和marginLeft。 This will nudge the bubble from its default position (which is also dependent on the arrow position declaration in your config)... 这会将气泡从默认位置轻推(这也取决于配置中的箭头位置声明)......

This is my code tweak in the bubble JS file which positions the bubble over the top of the marker (due to a design feature)... 这是我在泡泡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_;

Hope that helps. 希望有所帮助。

In the InfoBubble buildDom function, add: 在InfoBubble buildDom函数中,添加:

bubble.className = 'bubble-container';

Now you have a CSS class for each InfoBubble, you can shift it using CSS margin. 现在你有一个每个InfoBubble的CSS类,你可以使用CSS边距移动它。

You can also use a defined anchor height; 您还可以使用定义的锚点高度;

var anchorHeight = YOURNUMBER;

line 874 infobubble.js 第874行infobubble.js

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM