在你有一个合理的标记数量的时候,使Google Map标记是很平常的。但是一旦你有几百个、甚至更多地标的时候,性能迅速的开始降低。在本文章中,我会告诉你一些提高性能的方法。同时我会放一个测试页面去比较它们的效率。

如果你是第一次使用Google Map的标记,我建议你先去了解一下在Google Map上使用标记的一些基本原理和操作。

The Marker Manager-Keeps track of them

您的第一选择可能是利用MarkerManager,因为它是一个由谷歌提供的实用工具库。首先要将标记添加到MarkerManager,而不是使用GMap2.addOverlay()逐个的将每一个Marker添加到Map。MarkerManager会不断跟踪你所有的标记。通过定义几个不同的zoom-levels,将可能会同时出现的Marker集合放在同一level上,避免在同一时间大量的Marker同时显示。

MarkerManager 最初比直接加入到地图中有些慢,但是这样添加的好处是你可以更好的控制它们。

使用addMarker(GMarker, minZoom, maxZoom?)将标记添加到MarkerManager,这个方法携带三个参数,第一个是你要添加的标记,后两个参数是可选的,但是界定了在什么level上这个标记是可见的。

A simple example

//Create a new map

var map=new GMap2(document.getElementById('map'));

map.setCenter(new GLatLng(59.5,14.0),6);

//Create a new instance of the MarkerManager

var mgr = new MarkerManager(map);

// Create a new marker

var marker = new GMarker(new GLatLng(59.0, 13.80));

// Add marker to the MarkerManager

mgr.addMarker(marker);

明显的,没有谁会想MarkerManager添加单一的标记,但是如果你有几百个标记,那么可能就要这么做了。

Bulk adding the markers

使用MarkerManager更高效的办法是,首先将所有标记添加到一个数组中,然后用addMarkers(markerArray, minZoom, maxZoom?)将这个数组添加到MarkerManager。

// Create a new instance of the MarkerManager

var mgr = new MarkerManager(map);

// Create marker array

var markers = [];

// Loop to create markers and adding them to the MarkerManager

for(var i = 0; i < 50; i += 0.1) {

var marker = new GMarker(new GLatLng(59.0 + i, 13.80 + i));

markers.push(marker);

}

// Add the array to the MarkerManager

mgr.addMarkers(markers);

// Refresh the MarkerManager to make the markers appear on the map

mgr.refresh();

请注意,在将存有标记数组添加到MarkerManager之后,必须调用mgr.refresh()。在逐个添加Marker的时候是不需要的。

附加方法

removeMarker(marker)

从MarkerManager中移除一个标记。

clearMarkers()

移除所有标记。

getMarkerCount(zoom)

返回在指定的zoom-level下的标记个数。

MarkerManager是Google提供的一个实用工具库。从下面的链接你可以下载源代码以及说明文档和例子。Google Maps MarkerManager SVN

http://gmaps-utility-library.googlecode.com/svn/trunk/markermanager/release/

Marker Light - Markers on a diet(高亮标记-首都标记)

Google的Pamela Fox 为减少复杂标记,从而提高效率的MarkerLight制作了一个简单的程序。这样做的代价是,真的仅仅是在地图上显示一个图片,但你不能与之交互。如果你不需要与程序交互,那么这种办法真的是一种简单的提高性能的办法,这样做唯一的区别就是你创建的是一个MarkerLight,而不是一个GMarker。

作者Pamelas后来解释了为什么这种方法会提高效率:

GMarker之所以耗时这么长是因为它实际上是由多个DOM元素构成-前景,阴影,打印版本,可点击区域等。

如果你的目的只是显示,那么你可以选择象MarkerLight那样创建一个带有背景URL的DIV那样去创建一个GOverlay的扩展(或者背景颜色、甚至更好的)

------Pamela Fox

以下是如何使用它:

map.addOverlay(new MarkerLight(latlng, {image: "red_dot.png"}));

red_dot.png这个图片是用于marker中的。这是最小最简单的一个。你可以尝试在Pamelas test page上用不同数量的标记测试效率。Download markerlight.js

Using Marker Light in combination with MarkerManager-结合MarkerManager使用Marker Light

用MarkerManager的集中式添加MarkerLight的好处很多,而且真的很简单,只是将二者结合起来。

mgr.addMarker(new MarkerLight(latlng, {image: "red_dot.png"}));

这样做的原因是你可以显示在不同缩放级别下不同数量的标记。这种方式可以确保不会有太多的标记在同一时间显示。

Clusterer - Only show what you need

另一种方法是使用ACME实验室群集Clusterer。这是一个第三方库,提供了更快捷的方式加入标记。它是在BSD许可证下发布,并免费提供。

只需要做两件事情,效率会更快:

1.只有当前可见的标记会被建立。

         2.如果有太多的标记需要显示,那么它们会组合在一起成为群集标记。 

这会让你的地图上即使有成千上万个标记依然能保持良好的性能。我的测试表明,这种方法的效率要显著快于使用MarkerManager的方式。

以下是如何使用它:

// Create a Clusterer object

var clusterer = new Clusterer(map);

// Create marker

var marker = new GMarker(new GLatLng(57.8, 14.0));

// Add marker to the map

clusterer.AddMarker(marker, 'text to infobox');

调用clusterer.RemoveMarker(marker)方法来从Map中移除标记。另外还有一些方法来改变标志的行为。

  1. 1.       clusterer.SetIcon(GIcon) 

改变簇的图标

  1. 2.       clusterer.SetMaxVisibleMarkers(n) 

设置标记最多可见的数量门限,默认值是150.

  1. 3.       clusterer.SetMinMarkersPerCluster(n)

为一个标记集合设置最少的标记数,默认值是5.

  1. 4.       clusterer.SetMaxLinesPerInfoBox(n)

设置信息框内文本的最大行数,默认值是10.

Download Clusterer2.js

ClusterMarker - Chunk 'em all up

ClusterMarker是一个根据GNU通用公共许可证发布的免费javascript库,可以集中添加标记。这个库的独特行在于它会自动检测标记,彼此相交和集成为一个标记群集。

下面的图片说明是如何工作的:

Images by Martin Pearman

该构造函数有两个参数,如下:

var cluster = new ClusterMarker(map, options).

Map是对一个有如下属性的对象引用的 map对象和选项的参考(map is a reference to the map object and options is an object literal that can have these properties:)

  1. 1.       clusterMarkerIcon [GIcon]

         将默认的簇标记图标更改为你所选择的图标。

  1. 2.       markers [array]

         所有你想传递给ClusterMarker的标记的数组

除了这些属性,你也可以使用类中的其他所有属性,查看完整的文档说明列表documentation

如下是如何使用最少的代码量,用ClusterMarker添加标记:

var markerArray = [];

// Insert code to fill the markerArray with markers...

// Creating a new cluster by adding the map and the markerarray

var cluster = new ClusterMarker(map, {markers: markerArray});

// Refreshing to show the added markers

cluster.refresh();

这段代码将会在地图上插入标记,如果他们足够近的话,就用一个图标表示他们。欲了解更多关于如何细粒度操作的几种方法和属性,有关详细说明类库是如何工作的,在Clustermarker 项目页面上有很多优秀的文档。Clustermarker Project page.

MarkerClusterer - The new kid in town

这个使用工具库的所有都是最新的,在我最初写这篇文章的时候还没有。这个库,是吴小溪写的,谷歌地图的开放源码工具库的一部分,易于使用,具有优良的性能。

像其他的类库一样,他们聚集在一起使其更容易有一个概观,减少了可见标记的数量。观看下面的图像,看看如何:

Image by Xiaoxi Wu

它的构造函数需要三个参数,第一个是地图的引用,第二个是一个GMarkers数组,第三个被选择的对象与文字。只有第一个参数是必须的。

var markers = [];

// Insert code to fill the markerArray with markers...

// Creating a new cluster by adding the map and the array of markers

var markerCluster = new MarkerClusterer(map, markers);

查看完整的说明文档和它的功能documentation。更多信息去GoogleGeo开发博客读MarkerClusterer: A Solution to the Too Many Markers Problem

Compare performance

Compare the different techniques on the Test page

我的灵感来自于Pamela Fox的对MarkerLight的测试页,我也做了一个我自己的测试页

,你也可以测试本文中所有不同做法的性能。

结果:

我在几个不同的浏览器运行了测试,每一个测试,我使用不同的技术添加500个标记,每次测试之间我刷新浏览器。所有的测试平台采用一个具有3.60 GHz的奔腾4处理器和超线程运行Windows XP的2 GB内存的PC。

Load times in milliseconds (ms)

在这个测试中,Clusterer2是所有技术中最快的一个。但是要知道这是不是真实的数据,因为我只能够测量从我提交它们到标记传递到地图的时间,而不是知道在地图上看见标记的实际时间。当考虑到这方面,我觉得MarkerClusterer是最快的技术,紧随其后的是ClusterMarker。

当谈到浏览器,性能最高的是带有绿色标记的浏览器,性能最差的带有红色标记的浏览器。毫无疑义,IE性能很差。谷歌浏览器和Safari整体上表现出,他们的javascript引擎和性能一直很快。

如果你有什么好的想法去改善这个测试,使之能够更好的衡量直到标记在地图上显示实际时间,请在评论中通过共享或我的主页联络我。Contact page.

结论

利用这篇文章中的技术,执行效果一般都很好,因为你没有一个令人难以置信的大量的标记。对于一些特殊的场合,这些技术并不能满足你的需求,你将不得不采取更加极端的措施,例如,创建一个大的覆盖层,覆盖所有的标记,但是这超出了本文的讲述范围。

我希望这些技术能 帮到你,Happy coding!

Feedback

#1楼

2010-07-29 23:47 by Q

thanks

http://pic.cnblogs.com/face/44970/20140528102814.png

#2楼

2010-07-30 08:30 by 通用C#系统架构

非常不错,推荐+1

http://pic.cnblogs.com/face/u35584.jpg

#3楼

2010-07-30 09:20 by a-peng

楼主你有测过过吗?我记得之前我测试过,还是一样拖垮你。
最后是改用,分批加载,即一次加载200个左右,过1,2秒再加载200个。

#4楼[楼主]

2010-07-30 09:42 by Happy Coding

@a-peng
测试过,但是ASP.NET再怎么弄也不会太快,不过一次500个还可以,后来我改用Silverlight了,想加多少加多少,我要求的不是大量数据,而是海量!

http://pic.cnblogs.com/face/u111584.jpg

#5楼

2010-07-30 10:41 by Jay.Ren

不错 !
之前在做Google Map 处理坐标还是直接请求坐标去打点 看来有待改进
不过请问楼主 请求地址是直接用地址还是用坐标:X、Y来的?
Google 请求坐标也是有限制(大约1W) ,如何处理

http://pic.cnblogs.com/face/u44752.jpg?id=15163452

#6楼[楼主]

2010-07-30 11:33 by Happy Coding

@Tom.Ren
我是用切图的原理直接访问的Google地图服务器,请求回来的是一张根据xyz以及level命名的图片流,这样我就不必去Google请求地址了,在我请求回来的本地图片操作即可

http://pic.cnblogs.com/face/u111584.jpg

#7楼

2010-08-04 13:51 by 恋恋の雪

你好,我想跟你交流一下GIS开发方面的知识,能否加我QQ63408506

#8楼20089732011/1/12 14:22:06

2011-01-12 14:22 by 123112311

使用Google地图API的时候遇到一个问题
我使用GPS采集坐标+图片。
现在想把图片和坐标定位到Google地图上,发现偏移了很多,
不知道这个怎么解决。希望有知道的人告诉我下,我的QQ:289841242,不胜感激。

如何在Google Map中处理大量标记(ASP.NET)(转)的更多相关文章

  1. 如何在google test中指定只运行一部分测试

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:如何在google test中指定只运行一部分测试.

  2. Google Map中的瓦片

    一.墨卡托投影google map使用的是EPSG:900913标准墨卡托投影(等角圆术地图投影)y = R*ln(tan(pi/4 + a/2))x = R*b当y等于piR时,投影图正好为一个正方 ...

  3. 如何在 Google 地图中添加标记和说明

    JS如下: (function() {     window.onload = function() {         // Creating an object literal containin ...

  4. 在Google map图上做标记,并把标记相连接

    <!DOCTYPE html> <html> <head> <title>GeoLocation</title> <meta name ...

  5. 如何在Google Maps 添加多个标记

    JS如下: (function() {     window.onload = function() {         // Creating an object literal containin ...

  6. Google Map API v2 (三)----- 地图上添加标记(Marker),标记info窗口,即指定经纬度获取地址字符串

    接上篇 http://www.cnblogs.com/inkheart0124/p/3536322.html 1,在地图上打个标记 private MarkerOptions mMarkOption; ...

  7. Android google map 两点之间的距离

    在Android google map中,有时候会碰到计算两地的距离,下面的辅助类就可以帮助你计算距离: public class DistanceHelper { /** Names for the ...

  8. 房产地图google map的初步应用点滴.3)(转)

    房产地图google map的初步应用点滴.1)房产地图google map的初步应用点滴.2)房产地图google map的初步应用点滴.3) 房产地图google map的初步应用点滴.4) go ...

  9. Android开发之Google Map

    2013-07-03 Google Map 提供三种视图: 1. 传统的矢量地图,提供行政区域.交通以及商业信息等. 2. 不同分辨率的卫星照片,与Google Earth 基本一样. 3. 地形地图 ...

随机推荐

  1. ios 网络数据下载和JSON解析

    ios 网络数据下载和JSON解析 简介 在本文中笔者将要给大家介绍ios中如何利用NSURLConnection从网络上下载数据,如何解析下载下来的JSON数据格式,以及如何显示数据和图片的异步下载 ...

  2. Unity-碰撞

    固定位置和角度 选择项目视图中的 Prefab. 打开检视面板中的 Rigidbody 标签可以看到 Constraints 项. 点击左边的三角形图标, 下面会进一步显示 Freeze Positi ...

  3. 从C到C++的升级

    C++的语言类型 C++是静态的强类型语言. 静态语言:数据类型在编译期间检查,因此在写程序时需要声明变量的类型 强类型语言:强调数据类型,不同的数据类型间的转换需要进行强制类型转换 C与C++的关系 ...

  4. VS代码清理批处理

    批处理清理VS工程 del /f /q /s *.ncb del /f /q /s *.sdf del /f /q /s /A H *.suo del /f /q /s *.ipch del /f / ...

  5. (原)Ubuntu16中使用nvidia官方提供的驱动,而非自带的驱动

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5638185.html 安装完ubuntu16后,显卡显示的是Gallium... 在“设置-软件和更新 ...

  6. java压缩文件出现中文乱码问题

    在项目中需要压缩文件下载,做完了发现有中文乱码问题,终于明白了. 引入ant.jar包 import org.apache.tools.zip.ZipEntry;   import org.apach ...

  7. 【转】WPF - 第三方控件

    WPF - 第三方控件 目前第三方控件在网上形成巨大的共享资源,其中包括收费的也有免费的,有开源的也有不开源的,合理的使用第三方控件将使项目组的工作事半功倍.比如项目中有些复杂的业务逻辑.有些绚丽的效 ...

  8. C# 文件/文件夹压缩

    一.ZipFile ZipFile类用于选择文件或文件夹进行压缩生成压缩包. 常用属性: 属性 说明 Count 文件数目(注意是在ComitUpdat之后才有) Password 压缩包密码 Siz ...

  9. 经典递归算法研究:hanoi塔的理解与实现

    关于hanoi塔的原理以及概念,请Google,访问不了去百度. 主要设计到C中程序设计中递归的实现: 主代码实现如下: void hanoi(int src, int dest, int tmp, ...

  10. UESTC_传输数据 2015 UESTC Training for Graph Theory<Problem F>

    F - 传输数据 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit  ...