如果lat / long上有多个标记,我该如何旋转地图标记

时间:2011-12-29 14:26:15

标签: google-maps

我有一组4个标记点都具有完全相同的纬度/经度。 (同一街道地址内的不同办公室)。

我正在使用谷歌地图api v3,有几个例子我必须在同一纬度/长度绘制多个标记(IE:不同的业务,但在同一建筑物内的不同套房)。

如何在N / S / E / W方向上为每个旋转自定义标记图标。 (当它们放大到x缩放级别以外时,North是所有标记的默认值。

如果需要,我可以张贴js进行地图绘制。

2 个答案:

答案 0 :(得分:2)

我可以想出一种方法来解决这个问题。我可以想到另外两种方法来解决更高级别的问题:如何制作具有非常接近纬度/长度位置的可见多个标记。

“旋转”标记

假设您从标记数据列表开始:lat / long值和其他一些数据(此处为text)。一些lat / long值相同或足够接近,因为没有区别。

markerLatLngs = [
  {lat: 49.010, lng: -133.00, text: "123 Main St #101"},
  {lat: 49.010, lng: -133.00, text: "123 Main St #105"},
  {lat: 49.020, lng: -133.13, text: "246 Cambie St"}
];

您有自定义标记,我们可以调用其图标和阴影myIconmyShadow

myIcon   = google.maps.MarkerImage(...);
myShadow = google.maps.MarkerImage(...);

制作图标和阴影图形的三个修改版本,分别旋转90°,180°和270°。将四组标记图像捆绑在两个四元素阵列中:

myIcon90    = google.maps.MarkerImage(...);
myShadow90  = google.maps.MarkerImage(...);
myIcon180   = google.maps.MarkerImage(...);
myShadow180 = google.maps.MarkerImage(...);
myIcon270   = google.maps.MarkerImage(...);
myShadow270 = google.maps.MarkerImage(...);

myIcons   = [myIcon, myIcon90, myIcon180, myIcon270];
myShadows = [myShadow, myShadow90, myShadow180, myShadow270];

现在,处理您的标记数据列表,为每个标记数据指定一个方向字段。您可以在页面中的JavaScript中执行此操作,但最好在生成标记列表的代码中执行此操作。给定纬度/经度的第一个条目得到方向值0.下一个得到1,下一个得到2,依此类推。不同纬度/经度的条目获取方向值为0。

有很多方法可以完成这项任务。您可以按纬度和经度对列表进行排序,以便相同的值聚集在一起。您可以进行强力二次搜索,将每个条目与之后的每个条目进行比较。您可以执行复杂的cluster analysis(请参阅SO问号cluster-analysisgrouping)。请记住,通常比较真实数字以确保平等,这通常容易出错。

无论如何,结果是标记数据的修改列表,并添加了方向。

markerLatLngs = [
  {lat: 49.010, lng: -133.00, text: "123 Main St #101", orientation: 0},
  {lat: 49.010, lng: -133.00, text: "123 Main St #105", orientation: 1},
  {lat: 49.020, lng: -133.13, text: "246 Cambie St", orientation: 0}
];

在代码中为列表中的每个条目创建标记的位置,您可能会进行如下调用:

...
m = new google.maps.Marker({
    position: google.maps.LatLng( 
                  markerLatLngs[i].lat, markerLatLngs[i].lng
              ),
    icon:     myIcon, 
    shadow:   myShadow, 
    ...});
...

更改此代码以使用orientation字段选择适当的图标和阴影:

...
m = new google.maps.Marker({
    position: google.maps.LatLng( 
                  markerLatLngs[i].lat, markerLatLngs[i].lng
              ),
    icon:   myIcons[markerLatLngs[i].orientation], 
    shadow: myShadows[markerLatLngs[i].orientation], 
    ...});
...

以上都是伪代码,所以你必须在使用之前对它进行润色,但希望它可以解决这个问题。

Marker Clusterer

第二种方法不会旋转您的标记图标,但确实提供了解决更高级别问题的方法,如何制作具有非常接近的纬度/经度位置的可见多个标记。

这是使用MarkerClusterer实用程序库。它允许您显示非常靠近的标记组的集合标记(例如,带有信息窗口的标记,列出所有包含标记的信息)。请参阅MarkerCluster advanced example以了解相关信息。

位置抵消

解决更高级别问题的第三种方法是将小纬度和经度偏移引入太靠近的标记的位置。结果将是许多紧密间隔的标记,而不是在同一位置的多个标记。

“小偏移”有多大?它是缩放级别的函数。要获得四个像素的偏移量,在缩放级别8处需要两倍于缩放级别9的纬度偏移。您可以忽略这一点,并且只生成具有偏移纬度/长度的标记列表,该列表将具有可见的分离放大了:

markerLatLngs = [
  {lat: 49.010, lng: -133.00, text: "123 Main St #101"},
  {lat: 49.010, lng: -132.95, text: "123 Main St #105"}, 
                   /* ^^^^^^   longitude offset +0.05 */
  {lat: 49.020, lng: -133.13, text: "246 Cambie St"}
];

或者您可以按整数单位为每个列表条目生成latOffset和lngOffset值,并根据缩放级别计算单个单位的纬度和经度调整。您需要将偏移量存储在MarkerOptions字典中(请参阅SO“Google Maps Marker Data”)。

/* list of marker data, with latitude and longitude offset */
/* in integer units                                        */
markerLatLngs = [
  {lat: 49.010, lng: -133.00, text: "123 Main St #101", 
                                  latOffset: 0, lngOffset: 0},
  {lat: 49.010, lng: -133.00, text: "123 Main St #105", 
                                  latOffset: 0, lngOffset: 1},
  {lat: 49.020, lng: -133.13, text: "246 Cambie St", 
                                  latOffset: 0, lngOffset: 0}
];

/* Store original position, and offsets, using marker options */
...
m = new google.maps.Marker({
    icon:      myIcon, 
    shadow:    myShadow, 
    original:  google.maps.LatLng( 
                   markerLatLngs[i].lat, markerLatLngs[i].lng 
               ),
    latOffset: markerLatLngs[i].latOffset,
    lngOffset: markerLatLngs[i].lngOffset
    ...});
...

然后,在缩放级别的每次更改(需要更新纬度和经度位置调整)时,迭代每个标记。根据原始偏移量乘以调整因子计算新位置,调整因子是缩放级别的函数。

/* update marker positions on each change of zoom level */
adjustLat = fComputeAdjustmentLat(zoomlevel);  
adjustLng = fComputeAdjustmentLng(zoomlevel);
/* iterate through markers. For each marker m: */   
m.setPosition( 
    google.maps.LatLng( 
        m.original.lat() + m.latOffset*adjustLat, 
        m.original.lng() + m.latOffset*adjustLng 
    )
);

这有点复杂!

同样,这只是伪代码,你必须在使用之前对其进行抛光。也许这三种方法中的一种对您和未来的读者都有用。

答案 1 :(得分:0)

我发现了Google MAP V3的两个扩展程序:infobox.jsmarkerwithlabel.js 两者都可以将图像DOM元素作为内容处理,然后我可以通过jQuery image rotate plugin进行旋转。

旋转后无需再次设置标记图像即可正常工作。

最佳的跨浏览器方式是使用不同角度的标记创建一个精灵,并根据角度改变标记的大小属性。

另一种非交叉浏览器的方式是使用CSS3转换,你可能想要创建一个自定义Overlay来执行此操作。或者,使用画布绘制到地图上。但是,你不会得到一个dom元素来捕获点击事件。