카메라 이동

카메라는 API 호출, 사용자의 제스처 등 다양한 방법으로 움직일 수 있습니다. API를 호출해 카메라를 움직이려면 CameraUpdate 객체와 moveCamera() 메서드를 사용합니다. CameraUpdate의 다양한 속성을 사용해 카메라의 위치, 애니메이션, 콜백 등을 지정할 수 있습니다.

API 호출로 카메라 이동하기

카메라를 움직이려면 먼저 카메라를 어떻게 움직일지를 나타내는 CameraUpdate 객체를 생성해야 합니다. CameraUpdate는 카메라를 이동할 위치, 방법 등을 정의하는 클래스입니다. CameraUpdate 객체는 오직 팩토리 메서드를 이용해서 생성할 수 있으며, CameraUpdate 클래스에 다양한 팩토리 메서드가 정의되어 있습니다. 다음은 몇 가지 팩토리 메서드에 대한 설명입니다.

  • toCameraPosition(): 카메라의 위치를 지정한 CameraPosition으로 움직입니다.
  • scrollTo(): 카메라의 대상 지점을 지정한 좌표로 변경합니다.
  • scrollBy(): 카메라의 대상 지점을 지정한 픽셀만큼 상하좌우로 이동합니다.
  • zoomTo(): 카메라의 줌 레벨을 지정한 값으로 변경합니다.
  • fitBounds(): 영역이 온전히 보이는 좌표와 최대 줌 레벨로 카메라의 위치를 변경합니다.

생성한 객체를 파라미터로 삼아 NaverMap.moveCamera()를 호출하면 카메라가 움직입니다.

다음은 대상 지점을 (37.5666102, 126.9783881)로 변경하도록 지정하는 CameraUpdate 객체를 만들고 NaverMap.moveCamera()를 호출해 카메라를 움직이는 예제입니다.

CameraUpdate cameraUpdate = CameraUpdate.scrollTo(new LatLng(37.5666102, 126.9783881));
naverMap.moveCamera(cameraUpdate);

Java

CameraUpdate cameraUpdate = CameraUpdate.scrollTo(new LatLng(37.5666102, 126.9783881));
naverMap.moveCamera(cameraUpdate);

Kotlin

val cameraUpdate = CameraUpdate.scrollTo(LatLng(37.5666102, 126.9783881))
naverMap.moveCamera(cameraUpdate)

애니메이션

생성한 CameraUpdate 객체를 이용해 moveCamera()를 호출하기 전에 CameraUpdate.animate()를 호출하면 카메라 이동에 애니메이션을 적용할 수 있습니다. 애니메이션이 지정되면 일정한 시간 동안 카메라가 목표 지점까지 서서히 움직입니다.

애니메이션 유형

CameraUpdate.animate()를 사용하면 카메라 이동에 애니메이션을 적용할 수 있습니다. animate()는 애니메이션의 유형을 의미하는 CameraAnimation 객체를 파라미터로 받습니다. CameraAnimation 열거형에 나열되어 있는 애니메이션 유형은 다음과 같습니다.

  • None: 애니메이션 없이 이동합니다. 기본값입니다.
  • Linear: 일정한 속도로 이동합니다.
  • Easing: 부드럽게 가감속하며 이동합니다. 가까운 거리를 이동할 때 적합합니다.
  • Fly: 부드럽게 축소됐다가 확대되며 이동합니다. 먼 거리를 이동할 때 적합합니다.

다음은 카메라 이동에 Easing 애니메이션을 적용하는 예제입니다.

CameraUpdate cameraUpdate = CameraUpdate.scrollTo(new LatLng(37.5666102, 126.9783881))
    .animate(CameraAnimation.Easing);
naverMap.moveCamera(cameraUpdate);

Java

CameraUpdate cameraUpdate = CameraUpdate.scrollTo(new LatLng(37.5666102, 126.9783881))
    .animate(CameraAnimation.Easing);
naverMap.moveCamera(cameraUpdate);

Kotlin

val cameraUpdate = CameraUpdate.scrollTo(LatLng(37.5666102, 126.9783881))
        .animate(CameraAnimation.Easing)
naverMap.moveCamera(cameraUpdate)

지속 시간

animate()duration 파라미터를 지정하면 애니메이션의 지속 시간을 변경할 수 있습니다. 단, 애니메이션의 유형이 None일 경우 시간은 무시됩니다. 또한 duration0일 경우 애니메이션의 유형을 지정하더라도 애니메이션 없이 이동합니다.

다음은 카메라 이동에 Fly 애니메이션을 적용하고 지속 시간을 1초로 지정하는 예제입니다.

CameraUpdate cameraUpdate = CameraUpdate.scrollTo(new LatLng(37.5666102, 126.9783881))
    .animate(CameraAnimation.Fly, 1000);
naverMap.moveCamera(cameraUpdate);

Java

CameraUpdate cameraUpdate = CameraUpdate.scrollTo(new LatLng(37.5666102, 126.9783881))
    .animate(CameraAnimation.Fly, 1000);
naverMap.moveCamera(cameraUpdate);

Kotlin

val cameraUpdate = CameraUpdate.scrollTo(LatLng(37.5666102, 126.9783881))
        .animate(CameraAnimation.Fly, 1000)
naverMap.moveCamera(cameraUpdate)

지속 시간을 지정하지 않으면 지도의 기본 애니메이션 시간이 적용됩니다. 기본 애니메이션 시간은 NaverMapdefaultCameraAnimationDuration 속성을 사용해 변경할 수 있습니다.

다음은 지도의 기본 애니메이션 시간을 500밀리초로 변경하는 예제입니다.

naverMap.setDefaultCameraAnimationDuration(500);

Java

naverMap.setDefaultCameraAnimationDuration(500);

Kotlin

naverMap.defaultCameraAnimationDuration = 500

애니메이션 취소

진행 중인 카메라 이동 애니메이션은 다양한 이유로 취소되거나 취소할 수 있습니다. NaverMap.moveCamera()를 호출해 새로운 카메라 이동을 시작하면 이전에 진행 중이던 카메라 이동이 자동으로 취소됩니다.

다음은 지속 시간이 2초인 카메라 애니메이션을 시작하고 1초 후 다른 카메라 이동을 시작해 기존 카메라 애니메이션을 취소하는 예제입니다.

LatLng coord1 = new LatLng(37.5666102, 126.9783881);
LatLng coord2 = new LatLng(37.57000, 126.97618);

// 2초간 카메라 애니메이션
naverMap.moveCamera(CameraUpdate.scrollTo(coord1).animate(CameraAnimation.Easing, 2000));

// 1초 후 다른 카메라 이동이 시작되며 기존 카메라 애니메이션이 취소됨
new Handler().postDelayed(() -> {
    naverMap.moveCamera(CameraUpdate.scrollTo(coord2).animate(CameraAnimation.Easing))
}, 1000);

Java

LatLng coord1 = new LatLng(37.5666102, 126.9783881);
LatLng coord2 = new LatLng(37.57000, 126.97618);

// 2초간 카메라 애니메이션
naverMap.moveCamera(CameraUpdate.scrollTo(coord1).animate(CameraAnimation.Easing, 2000));

// 1초 후 다른 카메라 이동이 시작되며 기존 카메라 애니메이션이 취소됨
new Handler().postDelayed(() -> {
    naverMap.moveCamera(CameraUpdate.scrollTo(coord2).animate(CameraAnimation.Easing))
}, 1000);

Kotlin

val coord1 = LatLng(37.5666102, 126.9783881)
val coord2 = LatLng(37.57000, 126.97618)

// 2초간 카메라 애니메이션
naverMap.moveCamera(CameraUpdate.scrollTo(coord1).animate(CameraAnimation.Easing, 2000))

// 1초 후 다른 카메라 이동이 시작되며 기존 카메라 애니메이션이 취소됨
Handler().postDelayed({
    naverMap.moveCamera(CameraUpdate.scrollTo(coord2).animate(CameraAnimation.Easing))
}, 1000)

NaverMap.cancelTransitions()를 사용해서 명시적으로 카메라 애니메이션을 취소할 수도 있습니다. 호출하면 현재 진행 중인 카메라 애니메이션이 취소되고 카메라가 현재 위치에 멈춥니다. 스톱 제스처가 활성화되어 있다면 사용자가 지도를 탭했을 때에도 동일한 결과가 일어납니다.

다음은 cancelTransitions()를 호출해 카메라 애니메이션을 취소하는 예제입니다.

// 2초간 카메라 애니메이션
naverMap.moveCamera(CameraUpdate.scrollTo(coord1).animate(CameraAnimation.Easing, 2000));

// 1초 후 cancelTransitions()가 호출되며 기존 카메라 애니메이션이 취소됨
new Handler().postDelayed(() -> {
    naverMap.cancelTransitions();
}, 1000);

Java

// 2초간 카메라 애니메이션
naverMap.moveCamera(CameraUpdate.scrollTo(coord1).animate(CameraAnimation.Easing, 2000));

// 1초 후 cancelTransitions()가 호출되며 기존 카메라 애니메이션이 취소됨
new Handler().postDelayed(() -> {
    naverMap.cancelTransitions();
}, 1000);

Kotlin

// 2초간 카메라 애니메이션
naverMap.moveCamera(CameraUpdate.scrollTo(coord1).animate(CameraAnimation.Easing, 2000))

// 1초 후 cancelTransitions()가 호출되며 기존 카메라 애니메이션이 취소됨
Handler().postDelayed({
    naverMap.cancelTransitions()
}, 1000)

콜백과 이벤트

CameraUpdate의 콜백 속성을 사용하면 한 번의 카메라 이동에 대한 결과 콜백을 받을 수 있습니다. 또한 NaverMap에 이벤트 리스너를 등록하면 지도에서 일어나는 모든 카메라 이동에 대한 이벤트를 받을 수 있습니다.

카메라 이동 콜백

finishCallback()cancelCallback()으로 콜백 객체를 지정하면 해당하는 CameraUpdate에 대한 카메라 이동이 완료됐거나 실패했을 때 콜백을 받을 수 있습니다. 카메라 이동에 애니메이션이 지정되어 있고 그 애니메이션이 취소되었을 경우 cancelCallback()에 지정된 콜백이 호출되고, 그 외의 경우에는 finishCallback()에 지정된 콜백이 호출됩니다. 즉, 카메라 이동에 애니메이션이 지정되지 않았으면 카메라 이동은 항상 성공적으로 완료된 것으로 간주됩니다.

다음은 카메라 이동 완료 및 실패 시 토스트를 표시하는 콜백을 지정하는 예제입니다.

CameraUpdate cameraUpdate = CameraUpdate.scrollTo(new LatLng(37.5666102, 126.9783881))
    .animate(CameraAnimation.Easing, 2000)
    .finishCallback(() -> {
        Toast.makeText(context, "카메라 이동 완료", Toast.LENGTH_SHORT).show();
    })
    .cancelCallback(() -> {
        Toast.makeText(context, "카메라 이동 취소", Toast.LENGTH_SHORT).show();
    });

naverMap.moveCamera(cameraUpdate);

Java

CameraUpdate cameraUpdate = CameraUpdate.scrollTo(new LatLng(37.5666102, 126.9783881))
    .animate(CameraAnimation.Easing, 2000)
    .finishCallback(() -> {
        Toast.makeText(context, "카메라 이동 완료", Toast.LENGTH_SHORT).show();
    })
    .cancelCallback(() -> {
        Toast.makeText(context, "카메라 이동 취소", Toast.LENGTH_SHORT).show();
    });

naverMap.moveCamera(cameraUpdate);

Kotlin

val cameraUpdate = CameraUpdate.scrollTo(LatLng(37.5666102, 126.9783881))
        .animate(CameraAnimation.Easing, 2000)
        .finishCallback {
            Toast.makeText(context, "카메라 이동 완료", Toast.LENGTH_SHORT).show()
        }
        .cancelCallback {
            Toast.makeText(context, "카메라 이동 취소", Toast.LENGTH_SHORT).show()
        }

naverMap.moveCamera(cameraUpdate)

카메라 변경 이벤트

어떤 이유에 의해서건 카메라가 움직이면 카메라 변경 이벤트가 발생합니다. NaverMap.addOnCameraChangeListener() 메서드로 OnCameraChangeListener를 등록하면 카메라 변경 이벤트를 받을 수 있습니다. 카메라의 위치가 변경되면 onCameraChange() 콜백 메서드가 호출됩니다.

onCameraChange()에는 reasonanimated 파라미터가 전달됩니다. reason은 이벤트를 발생시킨 카메라 이동의 원인입니다. CameraUpdate.reason()을 호출해 카메라 이동의 원인을 지정할 수 있으며, 이벤트 리스너 내에서 이 값을 이용해 어떤 원인에 의해 발생한 이벤트인지를 판단할 수 있습니다. 제스처, 컨트롤 등 네이버 지도 SDK의 내장 기능에 의해 카메라가 이동한 경우 미리 정의된 음숫값을 가지며, 개발자가 임의의 양숫값을 지정할 수도 있습니다. 미리 정의되어 있는 원인은 다음과 같습니다.

  • REASON_DEVELOPER: 개발자가 API를 호출해 카메라가 움직였음을 나타냅니다. 기본값입니다.
  • REASON_GESTURE: 사용자의 제스처로 인해 카메라가 움직였음을 나타냅니다.
  • REASON_CONTROL: 사용자의 버튼 선택으로 인해 카메라가 움직였음을 나타냅니다.
  • REASON_LOCATION: 위치 트래킹 기능으로 인해 카메라가 움직였음을 나타냅니다.

animated는 이벤트를 발생시킨 카메라 이동에 애니메이션이 지정되어 있는지 여부를 나타냅니다.

다음은 카메라 변경시 원인을 로깅하는 이벤트 리스너를 등록하고, 원인을 지정해 카메라를 이동시키는 예제입니다.

naverMap.addOnCameraChangeListener((reason, animated) -> {
    Log.i("NaverMap", "카메라 변경 - reson: " + reason + ", animated: " + animated);
});

CameraUpdate cameraUpdate = CameraUpdate.scrollTo(new LatLng(37.5666102, 126.9783881))
    .animate(CameraAnimation.Easing, 2000)
    .reason(1000);

naverMap.moveCamera(cameraUpdate);

Java

naverMap.addOnCameraChangeListener((reason, animated) -> {
    Log.i("NaverMap", "카메라 변경 - reson: " + reason + ", animated: " + animated);
});

CameraUpdate cameraUpdate = CameraUpdate.scrollTo(new LatLng(37.5666102, 126.9783881))
    .animate(CameraAnimation.Easing, 2000)
    .reason(1000);

naverMap.moveCamera(cameraUpdate);

Kotlin

naverMap.addOnCameraChangeListener { reason, animated ->
    Log.i("NaverMap", "카메라 변경 - reson: $reason, animated: $animated")
}

val cameraUpdate = CameraUpdate.scrollTo(LatLng(37.5666102, 126.9783881))
        .animate(CameraAnimation.Easing, 2000)
        .reason(1000)

naverMap.moveCamera(cameraUpdate)

카메라 대기 이벤트

카메라의 움직임이 끝나 대기 상태가 되면 카메라 대기 이벤트가 발생합니다. NaverMap.addOnCameraIdleListener() 메서드로 OnCameraIdleListener를 등록하면 카메라 대기 이벤트를 받을 수 있습니다. 카메라가 대기 상태가 되면 onCameraIdle() 콜백 메서드가 호출됩니다.

카메라는 다음과 같은 시점에 대기 상태가 된 것으로 간주되어 이벤트가 발생합니다.

  • 카메라가 애니메이션 없이 움직일 때. 단, 사용자가 제스처로 지도를 움직이는 경우 제스처가 완전히 끝날 때까지(ACTION_UP이 발생할 때까지)는 연속적인 이동으로 간주되어 이벤트가 발생하지 않습니다.
  • 카메라 애니메이션이 완료될 때. 단, 카메라 애니메이션이 진행 중일 때 새로운 애니메이션이 발생하거나, 기존 카메라 이동의 finishCallback() 또는 cancelCallback()으로 지정된 콜백 내에서 카메라 이동이 일어날 경우 연속적인 이동으로 간주되어 이벤트가 발생하지 않습니다.
  • NaverMap.cancelTransitions()가 호출되어 카메라 애니메이션이 명시적으로 취소될 때.

다음은 카메라가 대기 상태가 되면 토스트를 표시하는 예제입니다.

naverMap.addOnCameraIdleListener(() -> {
    Toast.makeText(context, "카메라 움직임 종료", Toast.LENGTH_SHORT).show();
});

Java

naverMap.addOnCameraIdleListener(() -> {
    Toast.makeText(context, "카메라 움직임 종료", Toast.LENGTH_SHORT).show();
});

Kotlin

naverMap.addOnCameraIdleListener { reason, animated ->
    Toast.makeText(context, "카메라 움직임 종료", Toast.LENGTH_SHORT).show()
}

피봇

CameraUpdate.pivot() 메서드를 사용해 피봇 지점을 지정할 수 있습니다. 피봇 지점은 화면의 왼쪽 위를 (0, 0), 오른쪽 아래를 (1, 1)로 삼는 비율값으로, 카메라를 움직일 때 기준점이 되는 화면상 지점을 의미합니다. 피봇 지점이 지정되면 이동, 줌 레벨 변경, 회전이 화면 중심이 아닌 해당 지점을 기준으로 이루어집니다.

예를 들어 피봇 지점을 (0.5, 0.8)로 지정하고 카메라를 이동하면, 카메라 이동이 완료된 후 (0.5, 0.8) 지점의 좌표가 카메라 이동의 대상 지점과 일치하게 됩니다. 동일한 피봇 지점을 지정하고 지도를 확대하면 지도의 중심이 아닌 (0.5, 0.8) 지점을 기준으로 지도가 확대됩니다. 따라서 피봇 지점을 지정하면 카메라 이동이 완료된 후 카메라의 위치가 카메라 이동에서 지정했던 위치와 다를 수 있습니다.

피봇은 카메라가 위치해야 하는 화면상 지점을 지정한다는 측면에서는 콘텐츠 패딩과 동일한 역할을 합니다. 그러나 NaverMap의 속성인 콘텐츠 패딩과 달리 피봇은 CameraUpdate의 속성이므로 하나의 카메라 변경에만 적용되며, 지도 객체에 영구적으로 영향을 미치지 않습니다.

다음은 피봇 지점을 (0.5, 0.8)로 지정하고 카메라를 이동시키는 예제입니다.

CameraUpdate cameraUpdate = CameraUpdate.scrollTo(new LatLng(37.5666102, 126.9783881))
    .pivot(new PointF(0.5f, 0.8f));

naverMap.moveCamera(cameraUpdate);

Java

CameraUpdate cameraUpdate = CameraUpdate.scrollTo(new LatLng(37.5666102, 126.9783881))
    .pivot(new PointF(0.5f, 0.8f));

naverMap.moveCamera(cameraUpdate);

Kotlin

val cameraUpdate = CameraUpdate.scrollTo(LatLng(37.5666102, 126.9783881))
        .pivot(PointF(0.5f, 0.8f))

naverMap.moveCamera(cameraUpdate)

이동 제한

NaverMap의 속성을 지정하면 카메라가 이동할 수 있는 영역과 최소 및 최대 줌 레벨을 제한할 수 있습니다.

최소 및 최대 줌 레벨

minZoommaxZoom 속성을 지정하면 카메라의 최소 및 최대 줌 레벨을 제한할 수 있습니다.

다음은 카메라의 줌 레벨을 5~18 범위로 제한하는 예제입니다.

naverMap.setMinZoom(5.0);
naverMap.setMaxZoom(18.0);

Java

naverMap.setMinZoom(5.0);
naverMap.setMaxZoom(18.0);

Kotlin

naverMap.minZoom = 5.0
naverMap.maxZoom = 18.0

카메라 영역 제한

extent 속성을 지정하면 카메라의 대상 지점을 영역 내로 제한할 수 있습니다. 카메라가 제한 영역을 벗어나도록 API를 호출하더라도 대상 지점이 영역 내로 조정됩니다.

다음은 카메라의 대상 지점을 한반도 인근으로 제한하는 예제입니다.

naverMap.setExtent(new LatLngBounds(new LatLng(31.43, 122.37), new LatLng(44.35, 132)));

Java

naverMap.setExtent(new LatLngBounds(new LatLng(31.43, 122.37), new LatLng(44.35, 132)));

Kotlin

naverMap.extent = LatLngBounds(LatLng(31.43, 122.37), LatLng(44.35, 132.0))

카메라 영역을 제한할 때 최소 줌 레벨도 함께 제한하는 것이 좋습니다. 그렇지 않으면 지도가 축소되었을 때 제한 영역이 너무 작게 나타날 수 있습니다.

results matching ""

    No results matching ""