如果纬度/经度上有多个标记,我如何旋转地图标记

Posted

技术标签:

【中文标题】如果纬度/经度上有多个标记,我如何旋转地图标记【英文标题】:how can i rotate a map marker if there is more than one marker on a lat/long 【发布时间】:2012-01-29 22:34:26 【问题描述】:

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

我使用的是 google maps api v3,在某些情况下我必须在同一纬度/经度上绘制多个标记(即:不同的企业,但在同一建筑物内的不同套房中)。

我如何才能在 N/S/E/W 方向上为每一个旋转自定义标记图标。 (当所有标记放大到超过 x 缩放级别时,北是所有标记的默认值。

如果需要,我可以发布用于地图绘制的 js。

【问题讨论】:

【参考方案1】:

我可以想出一种方法来解决这个问题,就像你提出的那样。我可以想到另外两种方法来解决更高级别的问题:如何使具有非常接近的纬度/经度位置的多个标记可见。

“旋转”标记

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

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], 
    ...);
...

以上都是伪代码,所以你必须在使用前对其进行润色,但希望它能传达你的想法。

标记聚类器

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

这是为了使用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 
    )
);

这有点复杂!

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

【讨论】:

谢谢吉姆,我从没想过按纬度/经度排序并以这种方式应用标记旋转。【参考方案2】:

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

这甚至在旋转后无需再次设置标记的图像即可工作。

或者

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

另一种非跨浏览器方式是使用 CSS3 转换,您可能需要创建自定义叠加层来执行此操作。或者,使用画布在地图上绘制。但是,您不会获得一个 dom 元素来捕获点击事件。

【讨论】:

你有一个例子说明你是如何做到的吗?

以上是关于如果纬度/经度上有多个标记,我如何旋转地图标记的主要内容,如果未能解决你的问题,请参考以下文章

将数据库中的多个纬度/经度点加载到谷歌地图标记中的好方法?

如何计算地图中不同标记的距离,然后选择至少一个

如何在 JPG 地图上叠加经度和纬度标记?

我想通过从 json 获取经度和纬度在谷歌地图上显示标记

如何将谷歌地图标记的纬度和经度发送到 Firebase - android? [关闭]

从谷歌标记获取纬度/经度