📦 ClusterManager: Naver Map 기반 커스텀 클러스터링 구현
ClusterManager는 Naver Map 위에서 대량 주문 데이터를 클러스터링하여 가시성 있게 표현하기 위한 커스텀 유틸입니다. 줌 레벨에 따라 유동적으로 클러스터링 범위를 조정하고, 클릭 이벤트에 따라 사용자 액션을 트리거합니다.
🚩 주요 기능
- Haversine 공식을 사용한 거리 기반 클러스터링
- 줌 레벨에 따라 동적으로 threshold(거리 임계값) 조정
- 마커 클릭 시 선택 상태 반영 및 카메라 이동
- 단일 마커/클러스터 마커 각각에 대한 커스텀 뷰 렌더링
📌 주요 필드
private val maxDistance = 350.0
private val minDistance = 10.0
private var selectedId: Int? = null
private val markers = mutableListOf<Marker>()
private var items: List<ClusterItem> = mutableListOf()
📍 클러스터링 핵심 로직
private fun grouping(items: List<ClusterItem>): List<Pair<LatLng, List<ClusterItem>>> {
val threshold = when (val zoom = naverMap.cameraPosition.zoom) {
in 18.0..Float.MAX_VALUE -> 10.0
in 17.0..18.0 -> 20.0
in 16.0..17.0 -> 50.0
in 15.0..16.0 -> 100.0
in 14.0..15.0 -> 200.0
// ... 생략 ...
else -> 5000.0
}
val clusters = mutableListOf<Pair<LatLng, List<ClusterItem>>>()
val visited = mutableSetOf<ClusterItem>()
for (item in items) {
if (item in visited) continue
val group = items.filter { other ->
!visited.contains(other) && calculateDistance(item, other) < threshold
}
visited.addAll(group)
clusters.add(calculateClusterCenter(group) to group)
}
return clusters
}
threshold를 세분화해서 계산 했습니다.
🗺️ 마커 렌더링
fun update() {
markers.forEach { it.map = null }
markers.clear()
val clusters = grouping(items)
clusters.forEach { (position, clusterItems) ->
val marker = Marker().apply {
this.position = position
this.tag = clusterItems
this.icon = // 클러스터 여부에 따라 뷰 생성 생략
setOnClickListener {
// 선택 마커 ID 저장 및 콜백 처리
true
}
}
marker.map = naverMap
markers.add(marker)
}
}
🔄 선택 초기화
fun clearSelection() {
selectedOrderId = null
update()
}
✍️ 사용 예시
val clusterManager = ClusterManager(naverMap, context)
clusterManager.setItems(listOfClusterItems)
✅ 적용 효과
- 마커 수가 많을 경우 시각적 복잡도 감소
- 사용자의 선택과 클러스터 정보를 자연스럽게 연결
- MapActivity와 연동하여 마커 선택 → 상세 정보 표시 가능
'Android' 카테고리의 다른 글
BackpressCallback (0) | 2024.05.29 |
---|---|
네트워크 체크 (0) | 2024.05.29 |