简体   繁体   English

谷歌地图V3自定义标记图像和fitBounds()

[英]Google maps V3 custom marker images and fitBounds()

I am trying to get my custom markers to show up on my map after i have used the fitBounds() method to fit the boundaries of the map to the markers themselves. 在我使用fitBounds()方法将地图的边界与标记本身相匹配后,我试图让我的自定义标记显示在我的地图上。

I have done this by looping over the markers array and then extending the boundaries of the map to incorporate the marker co-ordinates. 我通过循环标记数组然后扩展地图的边界以合并标记坐标来完成此操作。

This works fine with the stock google maps markers. 这适用于股票谷歌地图标记。 However, my client wants to use quite large (36px by 57px) marker images for their site. 但是,我的客户希望为他们的网站使用相当大的(36px×57px)标记图像。 How do i compensate for this when fitting the boundaries of the map? 在拟合地图边界时如何补偿?

At the moment when using the custom marker images they do not all fit inside the boundaries set. 在使用自定义标记图像时,它们并不都适合设置的边界。

Since you already have calculated the bounds, you may just need to extend the bounds to add enough buffer area to include the large images. 由于您已经计算了边界,因此您可能只需要扩展边界以添加足够的缓冲区以包含大图像。 The formula you can use to calculate or extend a bounds this way is called a convex hull; 可用于以这种方式计算或扩展边界的公式称为凸包; the Computational Geometry Algorithms Library has a section on 2D Convex Hull Algorithms or there is a JavaScript Quickhull Article that also includes a nifty online example near the bottom of the page. 计算几何算法库有一个关于2D凸壳算法的部分,或者有一个JavaScript Quickhull文章 ,其中还包括页面底部附近的一个漂亮的在线示例。 Hope this is helpful - 希望这有用 -

The cheap answer is to always zoom out one level after fitBounds(). 便宜的答案是在fitBounds()之后总是缩小一个级别。 But we can do a bit better. 但我们可以做得更好。

I like writing hacks. 我喜欢写黑客。 Here I am making the assumption that the size of your marker will never be larger than 36x57. 在这里,我假设您的标记的大小永远不会大于36x57。 I tested a while back to find that fitBounds() leaves a margin of around 42 px between the edge and the closest marker (maybe not on mobiles), and I'm also assuming you are not repositioning the marker, that is, it will always be displayed above the given coordinate position. 我测试了一段时间后发现fitBounds()在边缘和最近的标记之间留下了大约42 px的边距(可能不在手机上),而且我还假设你没有重新定位标记,也就是说,它会始终显示在给定坐标位置上方。 If icons run off to the other sides, adjustments are needed. 如果图标跑到另一边,则需要进行调整。

My hack takes advantage of a function that measures the pixel position of a LatLng (using the container version, I read here that the div version is not reliable with bounds changes). 我的hack利用了一个测量LatLng像素位置的函数(使用容器版本,我在这里读到div版本在边界变化时不可靠)。

Since we know the height of the icon, and where the topmost marker is, we can pan the map south a bit if it's determined to be offscreen. 由于我们知道图标的高度以及最顶部标记的位置,因此如果确定在屏幕外,我们可以将地图向南平移一点。 In case there's not enough margin below, the only option is to zoom out. 如果下面没有足够的边距,唯一的选择是缩小。 My only concern is it will be jerky because it calls for two events: fitBounds and the custom panning/zooming. 我唯一担心的是它会生涩,因为它需要两个事件:fitBounds和自定义平移/缩放。 The only answer then would be to rewrite a custom fitBounds. 那么唯一的答案就是重写自定义的fitBounds。 When I tested manually the events ran smoothly. 当我手动测试时,事件顺利进行。

http://jsfiddle.net/sZJjY/ http://jsfiddle.net/sZJjY/

Click to add cat icons, right-click to trigger the resize/panning. 单击以添加猫图标,右键单击以触发调整大小/平移。

Example: place 3-4 kitties, right-click, then purposely place another that goes off the top, right-click again. 示例:放置3-4个小猫,右键单击,然后故意放置另一个从顶部开始,再次右键单击。

  function fitIcons() {
    var left = 180.0;
    var right = -180.0;
    var top = -90.0;
    var bottom = 90.0;

    for (var i = 0; i < markers.length; i++) {
      curlat = markers[i].getPosition().lat();
      curlng = markers[i].getPosition().lng();
      if(curlat > top)    { top = curlat; }
      if(curlat < bottom) { bottom = curlat; }
      if(curlng > right)  { right = curlng; }
      if(curlng < left)   { left = curlng; }
    }

    var overlay = new google.maps.OverlayView();
    overlay.draw = function() {};
    overlay.setMap(map);

    map.fitBounds(new google.maps.LatLngBounds(
      new google.maps.LatLng(bottom, left),
      new google.maps.LatLng(top, right)));

    topPixels = overlay.getProjection().fromLatLngToContainerPixel(
                  new google.maps.LatLng(top, right));

    bottomPixels = overlay.getProjection().fromLatLngToContainerPixel(
                  new google.maps.LatLng(bottom, left));

    topGap = topPixels.y;
    bottomGap = $("#map_canvas").height() - bottomPixels.y;

    if(topGap < iconHeight) {
      if(bottomGap > iconHeight) {
        map.panBy(0, topGap);
      }
      else {
        map.setZoom(map.getZoom() - 1);
      }
    }
  }

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

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