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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10866098/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 03:19:49  来源:igfitidea点击:

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

javascriptgoogle-mapsgoogle-maps-api-3infobubble

提问by Undefined

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. This has turned out to be harder than expected.

我正在尝试实现一个自定义 infoBubble,它将框打开到标记的一侧,而不是顶部的默认位置。事实证明,这比预期的要困难。

Using the normal infoWindow you can use pixelOffset. See here for the documentation

使用普通的 infoWindow,您可以使用 pixelOffset。有关文档,请参阅此处

Using infoBubble this does not seem to be the case. Is there anyway of using pixelOffset in an infoBubble, or something that will do the same thing?

使用 infoBubble 似乎并非如此。有没有在 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

我发现这很难搜索,因为使用这样的谷歌搜索不会返回任何相关结果谷歌搜索

Below is all my resources I have been using.

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

  • Example of infoBubble here.

  • My JavaScript to setup the map and infoBubble here.

  • infoBubble 的例子在这里

  • 我的 JavaScript 在这里设置地图和 infoBubble 。

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. Preferably to the right hand side of the marker.

为了获得赏金,我需要看到一个 infoBubble 的示例,该示例远离其标记上方的默认位置。最好在标记的右手边。

Update 3

更新 3

I have removed the testcase from update 1 because it is hosted on my old company's servers.

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

采纳答案by Suvi Vignarajah

It seems as though the infoBubble library itself defaults to positioning the bubble above the marker it is bound to. 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. Specifically notice from line 99 to line 122 and the use of the two infobubbles. 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. Now, based on this understanding I've created an example for you in this fiddle http://jsfiddle.net/pDFc3/. The infoBubble is positioned to the right of the marker.

似乎 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 位于标记的右侧。

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);I doesn't work. On the contrary, declaring infoBubble.getPosition();after the DOM loads gives me the current position of the marker the infoBubble is bound to. 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).

这很奇怪,因为 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.getPosition();在 DOM 加载后声明给了我 infoBubble 绑定到的标记的当前位置。所以 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/). 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:

我已经修复了我的 jsFiddle 来解决放大和缩小时的问题,并相应地定位 infoBubble ( http://jsfiddle.net/pDFc3/)。我先解释一下逻辑。首先,谷歌地图上道路地图类型的最大缩放级别是 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). So, based on this logic I added the following piece to find the initial longitudinal distance between marker and infoBubble:

在我们的例子中,初始距离的合理值为 0.00003 度(标记和信息气泡之间)。因此,基于此逻辑,我添加了以下部分来查找标记和 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. So that the method calls aren't repeated and slow your code down.

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

回答by Anubhav Gupta

This is my solution.

这是我的解决方案。

In InfoBubblelibrary

InfoBubble图书馆

replace

代替

entire InfoBubble.prototype.drawmethod

整个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);to set InfoBubble position

那么最后我们要使用这个方法setBubbleOffset(x,y);来设置InfoBubble的位置

infoBubble.setBubbleOffset(0,-32);

回答by Tim Dodd

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". Go into this file and search for...

您将使用“infoBubble”的 Google JS 文件。进入这个文件并搜索...

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. This will nudge the bubble from its default position (which is also dependent on the arrow position declaration in your config)...

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

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.

希望有帮助。

回答by bcm

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 边距移动它。

回答by Vlad Minaev

Unfortunately there is no such option as pixelOffset in InfoBubble. But if you just want to move up Bubble above the marker in your example you should not set mapparameter at bubble initialization. Consider the following fiddle (i fixed it for you):

不幸的是,InfoBubble 中没有像 pixelOffset 这样的选项。但是,如果您只想在示例中将 Bubble 向上移动到标记上方,则不应在气泡初始化时设置map参数。考虑以下小提琴(我为你修好了):

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

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



P.S. 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

回答by Dtnand

You can also use a defined anchor height;

您还可以使用定义的锚点高度;

var anchorHeight = YOURNUMBER;

line 874 infobubble.js

第 874 行 infobubble.js