簡析百度地圖點聚合功能----ClusterManager類
在百度地圖提供的Demo中,已經提供了一個很簡單的點聚合的demo程式,主要用到的類就是ClusterManager<T>用來管理各個Marker的聚合,
另外就添加了一個實現了ClusterItem介面的MyItem,用來管理各個Marker的資料。
demo實在太簡單了,要實現自己的功能還是得去啃與Cluster相關的類,很累人!!
剛好最近有這方面的需求,就去啃了一把cluster相關原始碼,在這裡分享一下。
一、說明
1.點聚合的核心演算法已經由百度地圖實現了,我們只需要管理好我們的資料和圖示
2.主要有三個類需要自己實現:ClusterItem, ClusterManager, DefaultClusterRenderer
二、具體介紹
1.ClusterItem介面,這個就是地圖上一個一個獨立的標記點。準確的說我們的點MyItem必須繼承ClusterItem這個介面,
才能被ClusterManager管理。
這個介面提供兩個方法需要實現:
一個是提供marker的位置,一個是提供marker的圖示。/** * ClusterItem represents a marker on the map. */ public interface ClusterItem { /** * The position of this marker. This must always return the same value. */ LatLng getPosition(); BitmapDescriptor getBitmapDescriptor(); }
所以,我們的MyItem類必須要有座標位置的變數。
如果,每個marker還有其他產品資料,可在MyItem中定義一個Bundle,用來儲存這個marker上的產品資料。(可以用來做點選顯示產品的功能)
2.ClusterManager類
這個類實現了兩個與BaiduMap相關的介面:OnMapStatusChangeListener 和 OnMarkerClickListener 。
本來ClusterManager提供了ClisterItem的點選回撥介面:OnClusterItemClickListener和OnClusterClickListener,
但現在的版本還無法使用,所以只能繼續使用OnMarkerClickListener來實現marker的點選事件,但是有一點要注意,
必須要將MyItem中的資料指定給相應的marker,才能在點選marker時獲取到marker的資料,否則marker中是無資料的。
那麼,MyItem中的資料是怎麼指定給marker的呢?
別急,答案就在下面那個類裡。
我們先來看一下ClusterManager的一些必要操作,呼叫addItems()函式來新增MyItem物件,然後呼叫cluster()函式,更新資料。
3.DefaultClusterRenderer類
把各個marker聚合和分離的操作都在這個類裡完成的,可以說這個才是真正的核心類。
上面說的將MyItem資料傳遞給marker的操作也在這個類中完成。
注意:如果自己實現了DefaultClusterRenderer則需要呼叫ClusterManager.setRenderer()函式將我們定義的Renderer傳進來。
在此類中有一個常量用來判斷幾個點才會聚合:MIN_CLUSTER_SIZE ,預設是4,我改成了1.
然後,這個類中的其他方法都不需要管,override下面四個方法就可以滿足我們的要求了。
在聚合操作之前所需要的設定,可對MarkerOptions進行一些所需要的設定。
/**
* Called before the marker for a ClusterItem is added to the map.
*/
protected void onBeforeClusterItemRendered(T item, MarkerOptions markerOptions) {
}
/**
* Called before the marker for a Cluster is added to the map.
* The default implementation draws a circle with a rough count of the number of items.
*/
protected void onBeforeClusterRendered(Cluster<T> cluster, MarkerOptions markerOptions)
在聚合操作完成之後的設定—— 可以將MyItem中的資料傳遞給Marker,以完成在點選時的資料展示。
/**
* Called after the marker for a Cluster has been added to the map.
*/
protected void onClusterRendered(Cluster<T> cluster, Marker marker) {
}
/**
* Called after the marker for a ClusterItem has been added to the map.
*/
protected void onClusterItemRendered(T clusterItem, Marker marker) {
}