最近用到了Google地圖進行開發,對Google地圖的API有了初步的認識。使用Google API開發一般都會用到Marker,用來標註位置。本文將對顯示大資料量的Marker進行研究和討論。
問題提出:
如果你需要在地圖上展示大資料量的Marker,就會發現兩個問題。
1、效能問題:如果在地圖上添加越多的Marker,使用起來就會感覺速度越慢。速度的快慢還取決瀏覽器和電腦的配置。在google瀏覽器上會比IE上快很多。
2、可用性問題。地圖上Marker越多,就會越不宜用。當然這還取決於Marker的密集度。如果這些Marker都很分散,關係不是很大。如果很密集,使用者就看不到地圖上的東西了。如:顯示10個、100個問題不大。當顯示1000個的時候,地圖被這些Marker佔據了。
顯示10個marker,沒有什麼問題
顯示100個,感覺有點擁擠了。
顯示1000個,根本看不到地圖上任何東西了。
解決方案:
方案一:減少顯示數量
1、在我們系統中,可以通過一個搜尋方塊。比如:通過搜尋,在地圖上標註深圳所有沃爾瑪超市的位置。
2、加過濾。原則跟上面一樣,減少顯示的Marker。如:加一個過濾機制,只標註人口超越100W的城市。
方案二:叢集顯示
前面兩種都是通過減少marker顯示的數量來解決問題的,下面看看如果不減少marker的數量來到底同樣的效果。方案就是通過叢集的方式。根據一定規則將Marker劃分到不同的群中。根據地圖的不同縮放層級顯示不同的marker叢集。當地圖縮放的時候,繼續將更多的相關的marker集中在這個組中,用這個組代替marker顯示。當放大到一定層級再顯示marker本身。如1000個marker展示為:
當縮小地圖顯示層級時,繼續進行相關叢集:
但放大地圖顯示層級的時候分散叢集:
那又根據什麼規則來叢集的呢?下面介紹三種叢集的方式:
1、基於網格:將地圖分割成很多網格。根據地圖不同的縮放層級的在同一個網格中的marker叢集在一個分組中。
2、基於距離:這個很好理解,將距離近的marker顯示在一個分組中。
3、基於分區:我們可以將地圖分成不同的分區,比如根據省份將地圖分成不同的分區。將省份中的marker集中在一起顯示。
樣本:
下面我通過例子來實現以上的效果。
1、使用MarkerClusterer,MarkerClusterer是一個google地圖第三方的類庫。它是基於網格分組的。
建立地圖:
// 建立地圖 var options = { zoom: 12, center: new google.maps.LatLng(22.50, 114.07), mapTypeId: google.maps.MapTypeId.ROADMAP }; var map = new google.maps.Map(document.getElementById('map'), options);
在可視的地圖範圍內建立1000個marker,並使用MarkerClusterer顯示
google.maps.event.addListenerOnce(map, 'bounds_changed', function() { // 擷取地圖分界線 var bounds = map.getBounds(); // 擷取地圖的角 var southWest = bounds.getSouthWest(); var northEast = bounds.getNorthEast(); // 計算地圖從上到下的距離 var latSpan = northEast.lat() - southWest.lat(); // 計算地圖從左至右的距離 var lngSpan = northEast.lng() - southWest.lng(); // 建立資料儲存Marker對象 var markers = []; // 建立一個迴圈 for (var i = 0; i < 1000; i++) { //建立隨機數 var lat = southWest.lat() + latSpan * Math.random(); var lng = southWest.lng() + lngSpan * Math.random(); var latlng = new google.maps.LatLng(lat, lng); // 建立Marker,注意它沒有添加到地圖上面 var marker = new google.maps.Marker({ position: latlng }); // 將Marker添加到數組中 markers.push(marker); } //建立一個MarkerClusterer對象,將marker數組對象傳遞給它 var markerclusterer = new MarkerClusterer(map, markers); });
2、使用markermanager。markermanager是基於分區的方式的。
下面我在定義兩個省份的marker:湖南和廣東。湖南這個分區中定義長沙、常德、永州三個城市。廣東定義廣州、深圳、東莞三個城市。但層級大於6顯示城市,否則顯示省份的叢集。代碼如下:
(function() { window.onload = function() { // 建立地圖 var options = { zoom: 5, center: new google.maps.LatLng(26.41, 111.61), mapTypeId: google.maps.MapTypeId.ROADMAP }; var map = new google.maps.Map(document.getElementById('map'), options); // 初始化MarkerManager var mgr = new MarkerManager(map); // 建立表示湖南的marker var hunan = new google.maps.Marker({ position: new google.maps.LatLng(28.19, 112.98), icon: 'img/cluster.png' }); // 給hunan添加一個點擊事件 google.maps.event.addListener(hunan, 'click', function() { //設定地圖的層級 map.setZoom(7); // 設定中心點 map.setCenter(hunan.getPosition()); }); // 建立表示廣東的marker var guangdong = new google.maps.Marker({ position: new google.maps.LatLng(22.50, 114.07), icon: 'img/cluster.png' }); // 給hunan添加一個點擊事件 google.maps.event.addListener(guangdong, 'click', function() { //設定地圖的層級 map.setZoom(7); // 設定中心點 map.setCenter(guangdong.getPosition()); }); var states = [hunan, guangdong]; // 建立湖南和廣東省的城市 var cities = [ // 永州 new google.maps.Marker({ position: new google.maps.LatLng(26.41155054662258, 111.610107421875) }), // 常德 new google.maps.Marker({ position: new google.maps.LatLng(29.017748018496046, 111.68701171875) }), // 衡陽 new google.maps.Marker({ position: new google.maps.LatLng(28.22697003891834, 112.91748046875) }), // 廣州 new google.maps.Marker({ position: new google.maps.LatLng(23.120153621695614, 113.2470703125) }), // 深圳 new google.maps.Marker({ position: new google.maps.LatLng(22.512556954051437, 114.0380859375) }), //東莞 new google.maps.Marker({ position: new google.maps.LatLng(22.998851594142913, 113.75244140625) }) ]; // 在使用MarkerManager之前,確保MarkerManager已經載入 google.maps.event.addListener(mgr, 'loaded', function() { // 這些marker在 1 到 5顯示 mgr.addMarkers(states, 1, 5); // 這些marker在大於6顯示 mgr.addMarkers(cities, 6); // 將MarkerManager添加到地圖上 mgr.refresh(); }); }; })();
叢集顯示:
點擊叢集,分散顯示marker。
總結:本文就google地圖大資料量的顯示進行了探索,介紹了幾種大資料量處理的方式。
代碼下載:http://files.cnblogs.com/zhuqil/WebApplication2.rar
參考:
http://code.google.com/intl/zh-CN/apis/maps/documentation/javascript/
http://google-maps-utility-libraryv3.googlecode.com/svn/tags/markerclusterer/1.0/
Beginning Google Maps API 3