Google Map: GMUClusterManager 設定最小聚集Zoom

A-Tân
May 29, 2021

--

最近工作上碰到Google Map,並用到GMUClusterManager,它的作用簡單來說,就是會自動聚合地圖上的Marker,當User把地圖縮小時,會自動把距離接近的Marker縮成一個點,假設是把五個各為1的Marker聚合,就會縮成一個顯示為5的Marker。

詳情可以看 法蘭克的iOS世界這篇貼文,有完整的說明跟gif,介紹得非常詳盡。

後來設計大大給了一個有點困難的需求,就是當User把圖持續縮小時,希望到了一個臨界點之後,就不要再進行聚合,停留在原本臨界點中聚合的狀態。

舉例來說,假設User進入地圖時,MapView的Camera的Zoom設為15,大約是「左下角:大安森林公園,右上角:南京復興站」的大小,此時地圖上有12個各為「1」的Marker;當User把地圖縮小,Zoom到12時大約是「上方:北投,下方:碧潭」的範圍,這時候地圖上有5個各為「50」的Marker,就是GMUClusterManager的神奇效果;

然後我們希望將12的這個Zoom設為臨界點,接下來User往下繼續縮小,縮到11、10、9……的時候,台北市都一樣停留在5個「50」的Marker,而不是將整個北部地區都群聚成1個「250」的Marker,這個需求該如何達成呢?

Google Map官方的文件中,有一篇關於Marker Clustering的文章,不過沒有特別提到任何上限、下限、最大、最小的觀念,除了「For best performance, the recommended maximum number of markers is 10,000」這句沒什麼用的描述。

GMUClusterManager中會用到的GMUDefaultClusterRenderer,有一個參數叫maximumClusterZoom,但如同它註解中寫的,”Sets the maximium zoom level of the map on which the clustering should be applied. At zooms above this level, clusters will be expanded.”,實際上的作用是讓任何大於它的Zoom,都不要再做任何群聚,例如設為15時,那放大到超過15後,就全部散開成一堆「1」的Marker,因此完全不是我們要的效果。

後來我再仔細看了一下官方文件,發現文件最後有提到一段Customize marker clustering

You can provide a custom implementation for the GMUClusterRenderer, GMUClusterIconGenerator, or GMUClusterAlgorithm. You can base your custom implementation on the sample implementation of these protocols included in the utility library, or you can code a fully custom implementation by fulfilling the protocols.

所以照著這個想法,我跑去翻了一下我們選用的GMUNonHierarchicalDistanceBasedAlgorithm的Code,發現.m檔中有一段- (NSArray<id<GMUCluster>> *)clustersAtZoom:(float)zoom的function,雖然Objective C要看懂真的有點難…不過大概猜一下,這段有輸入型別為floatzoom,輸出的則是GMUCluster,那應該就是這段在處理Zoom跟群聚的邏輯。

因此,照著文件試試看,我設了一個自訂的class,繼承GMUNonHierarchicalDistanceBasedAlgorithm ,並override上述的function,用super去輸出它原本的邏輯,但加入zoom的判斷條件,結果如下:

然後在放入地圖的View Controller裡宣告GMUClusterManager 的時候,用這個我自己客制的Algorithm 的 class:

結果就成功了!當user把地圖縮小到小於12時,地圖上群聚的UI真的就停留在12的階段,不會再進一步群聚!

希望這篇文可以幫助到有需要的人 :)

--

--