Animation

KakaoMapsSDK의 객체에 Animation 을 적용하는 방법.

Animation

자연스러운 지도 렌더링을 위한 애니메이션 기능을 제공합니다. 지도 위에 표시되는 객체 중 일부 타입(ex.Poi)은 두 가지 종류의 간단한 애니메이션 효과를 적용할 수 있습니다.

Animation type Description
Transition 지도 위 객체가 나타나거나 사라질 때, 적용할 수 있는 애니메이션입니다. 스타일을 지정하여 객체에 애니메이션 효과를 적용할 수 있습니다.
moveAt/rotateAt 지도 위 객체가 이동&회전을 할 때 적용되는 애니메이션입니다. 각 객체별로 적용할 수 있도록 interface가 제공됩니다.

Animator


Animator는 위 두 가지 종류의 애니메이션과는 다르게 객체에 animation 효과를 적용할 수 있습니다. Animator는 animation을 실행하는 일종의 그룹과 같은 형태로, Animator 그룹에 애니메이션 효과를 적용 할 객체를 여러개 넣을 수 있으며, 위에서 언급한 두 가지 애니메이션보다 좀 더 복잡한 애니메이션 효과를 적용할 수 있습니다. 객체마다 적용할 수 있는 Animation효과는 다르지만, 현재 아래와 같은 AnimationEffect를 제공합니다. 특정 AnimationEffect를 적용하여 생성한 Animator는 사용자가 직접 객체를 넣어서 애니메이션 효과가 동작하거나 정지할 수 있도록 start/stop 형태의 인터페이스를 제공합니다.

Animation Effect Description 적용할 수 있는 Object
DropAnimationEffect 화면상 특정 px만큼 떨어지는 애니메이션 효과 Poi, InfoWindow
WaveAnimationEffect 화면상 특정 px만큼 퍼지거나 줄어드는 형태의 물결 형태의 애니메이션 효과 Shape
KeyFrameAnimationEffect 지정된 keyframe에 따라 연속적으로 변화하는 애니메이션. 위치, 크기, 회전 값이 변화하는 효과를 줄 수 있음. Poi

Animator는 아래와 같은 규칙을 가지고 동작합니다.

- Animator에 추가된 객체가 없을경우 Animator는 동작하지 않습니다.
- Animator를 start한 이후에는 Animator에 객체를 추가하거나 Animator에 있는 객체를 비우는등의 함수는 무시됩니다. 즉, 객체를 추가하거나 Animator를 비우려면 반드시 stop을 호출한 이후에 수행해야 합니다.
- Animator에 추가된 객체는 1회성 성격을 가지고 있습니다. 즉, Animator가 start 한 이후 stop을 호출하거나 Animation이 종료되면 Animator에 추가되어있던 모든 객체는 비워집니다. 따라서, 같은 애니메이션 효과를 반복해서 주고싶다면 Animation동작이 끝날때마다 객체를 다시 Animator에 추가해주어야 합니다.
- moveAt / rotateAt 등 이동 회전의 애니메이션을 하는 도중에 Animator를 동작시킬경우 기존에 진행하던 이동/회전 애니메이션은 취소됩니다.
  • Poi Animator

LabelManager에서는 PoiAnimator의 추가 및 삭제등을 관리하고 있습니다. 한번 생성한 Animator는 지우기전까지 LabelManager에서 관리하고 있으므로, ID를 이용해서 LabelManager에서 가져올 수 있습니다. 생성한 Animator에는 Poi를 추가할 수 있으며, Animator를 동작시키면 Animator에 속한 모든 Poi에 일괄적으로 애니메이션 효과가 적용됩니다.

PoiAnimator

PoiAnimator는 LabelManger를 통해 생성 할 수 있습니다. 이 때, Animator가 가질 PoiAnimationEffect종류에 해당하는 Animator 효과를 지정할 수 있습니다. 현재까지는 PoiAnimationEffect종류는 DropAnimationEffect만 존재합니다. 생성된 PoiAnimator에 Poi를 추가하면 Animator를 동작시킬 수 있습니다.

아래 예제 코드는 DropAnimationEffect 효과를 적용한 PoiAnimator 예제입니다.

func createPoi(position: MapPoint, hide: Bool) {
        let view = mapController?.getView("mapview") as! KakaoMap
        let manager = view.getLabelManager()
        let layer = manager.getLabelLayer(layerID: "PoiLayer")
        let poiOption = PoiOptions(styleID: "customStyle1")
        poiOption.rank = 0
        
        let poi = layer?.addPoi(option:poiOption, at: position)
        poi!.show()
        
        // DropAnimationEffect를 적용한 PoiAnimator를 추가한다.
        let animator = manager.addPoiAnimator(animatorID: "drop_animator_" + String(_index), effect: DropAnimationEffect(pixelHeight: 500), interpolation: AnimationInterpolation(duration: 1000, repeat: 1, method: .cubinIn), hideAtStop: hide)
        
        // 생성한 Animator에 Poi를 추가한다.
        animator?.addPoi(poi!)
        
        // Animator를 start하면, Poi가 DropAnimationEffect에 따라 애니메이션 효과가 동작한다.
        animator?.start()
 }
  • InfoWindow Animator

GuiManager에서는 이 Animator의 추가 및 삭제를 관리하고 있습니다. 한번 생성한 Animator는 지우기 전까지 GuiManager에서 관리하고 있으므로, ID를 이용해서 GuiManager에서 가져올 수 있습니다.

생성된 Animator에 InfoWindow를 추가할 수 있으며, Animator를 동작시키면 Animator에 속한 모든 InfoWindow에 일괄적으로 애니메이션 효과가 적용됩니다.

InfoWindowAnimator

InfoWindowAnimator는 GuiManager를 통해 생성할 수 있습니다. 이 때, Animator에 적용될 InfoWindowAnimationEffect 종류에 해당하는 Effect를 지정할 수 있습니다. 현재까지 InfoWindowAnimationEffect는 DropAnimationEffect만 존재합니다.

아래 예제 코드는 DropAnimationEffect를 적용한 InfoWindowAnimator 예제입니다.

    //InfoWindow에 DropAnimation효과를 주기 위해 Animator를 생성한다.
   func createInfoWindowAnimator() {
       let view = mapController?.getView("mapview") as! KakaoMap
       let manager = view.getGuiManager()
        // 생성한 InfoWindow를 가져온다.
       let infoWindow = manager.getGui(guiName: "infoWindow") as! InfoWindow
       
       // InfoWindow Animator 생성. DropAnimationEffect를 적용한다.
       let animator = manager.addInfoWindowAnimator(animatorID: "drop_animator", interpolation: AnimationInterpolation(duration: 1000, repeat: 1, method: .cubinIn), effect: DropAnimationEffect(pixelHeight: 800), hideAtStop: false)

       animator?.addInfoWindow(infoWindow) // animator에 InfoWindow를 추가한다.
       
       animator?.start() // animator 시작. animator에 들어가있는 InfoWindow에 애니메이션 효과가 적용된다.
   }
  • Shape Animator

ShapeManager에서는 ShapeAnimator의 추가 및 삭제등의 관리를 하고 있습니다. 한번 생성한 Animator는 지우기 전까지 ShapeManager에서 관리하고 있으므로, ID를 이용해서 ShapeManager에서 가져올 수 있습니다.

생성한 Animator에는 Shape(PolygonShape, PolylineShape, MapPolygonShape, MapPolylineShape)를 추가할 수 있으며, Animator를 동작시키면 Animator에 속한 모든 Shape에 일괄적으로 애니메이션 효과가 적용됩니다.

ShapeAnimator

ShapeAnimator는 ShapeManager를 통해서 생성할 수 있습니다. 이 때, Animator가 가질 ShapeAnimationEffect 종류인 애니메이션 효과를 지정할 수 있습니다. 현재까지 ShapeAnimationEffect 종류는 WaveAnimationEffect만 존재합니다. WaveAnimationEffect는 시작할때 알파&스케일값과 끝날때 알파&스케일 값을 지정하여 애니메이션 진행에 따라 Fade-In/Out효과와 점점 커지거나 작아지는 형태의 애니메이션 효과를 줄 수 있습니다. WaveAnimationEffect의 Property는 아래와 같습니다.

Property Description
startAlpha 애니메이션이 시작할때의 알파값
endAlpha 애니메이션이 끝날때의 알파값
startPixel 애니메이션이 시작할때의 radius(px)값. 이 픽셀값과 유사하게 폴리곤이 보이려면, Polygon의 반지름을 1.0정도로 설정하는것을 권장합니다.
endPixel 애니메이션이 끝날때의 radius(px)값. 이 픽셀값과 유사하게 폴리곤이 보이려면, Polygon의 반지름을 1.0정도로 설정하는것을 권장합니다.

또한 WaveAnimationEffect는 Style과 유사하게 레벨별로 효과를 다르게 설정할 수 있습니다.

아래 예제 코드는 WaveAnimationEffect를 PolygonShape에 적용한 ShapeAnimator 예제입니다.

    func createShape() {
        let mapView: KakaoMap? = mapController?.getView("mapview") as? KakaoMap
        let manager = mapView?.getShapeManager()
        // ShapeLayer 생성
        let layer = manager?.addShapeLayer(layerID: "shapeLayer1", zOrder: 10001)
        
        // 0~14레벨까지 표시하는 스타일
        let shapeStyle = PerLevelPolygonStyle(color: UIColor(red: 0.7, green: 0.7, blue: 0.7, alpha: 0.5), storkeWidth: 2, strokeColor: UIColor.blue, level: 0)
        
        // 15~21까지 표시하는 스타일
        let shapeStyle2 = PerLevelPolygonStyle(color: UIColor(red: 0.7, green: 0.0, blue: 0.0, alpha: 0.5), storkeWidth: 2, strokeColor: red, level: 15)
        
        // 0~14 / 15~21 로 지정된 스타일 생성
        let shapeLevelStyle = PolygonStyle(styles: [shapeStyle1, shapeStyle2])
        
        // styleSet생성. styleSet에는 1개의 스타일만 존재한다.
        let styleSet = PolygonStyleSet(styleSetID: "shapeLevelStyle1")
        styleSet.addStyle(shapeLevelStyle)
        
        manager?.addPolygonStyleSet(styleSet)

	// PolygonShape 생성 옵션.
        let options = PolygonShapeOptions(shapePointType: .relative, shapeID: "shape1", styleID: "shapeLevelStyle1", zOrder: 1)
        let viewSize = mapView!.viewRect().size
        options.basePosition = (mapView?.getPosition(CGPoint(x: viewSize.width/2, y: viewSize.height/2)))!
        options.polygons.append(Polygon(exteriorRing: Polygon.getCirclePoints(radius: 1.0, cw: true), hole: nil))
       
        // PolygonShape 생성.
        let shape = layer?.addPolygonShape(options)
        shape?.show()
        
        // animator 생성. 레벨별로 지정할 수 있다.
        let effect = WaveAnimationEffect
        ()
        effect.addAnimationData(startAlpha: 0.8, endAlpha: 0.0, startPixel: 10.0, endPixel: 100.0, level: 0) // 0~14까지 적용될 애니메이션 효과
        effect.addAnimationData(startAlpha: 0.8, endAlpha: 0.0, startPixel: 50, endPixel: 500, level: 15) // 15~21까지 적용될 애니메이션 효과
        
        // 애니메이터를 추가한다. 
        let animator = manager?.addShapeAnimator(animatorID: "circleWave", interpolation: AnimationInterpolation(duration: 1500, repeat: 15, method: .cubicOut), effect: effect, hideAtStop: true)
        
        // 애니메이터에 PolygonShape를 추가한다.
        animator?.addPolygonShape(shape!)
        
        // 애니메이터 start.
        animator?.start()
    }

위 코드를 실행시키면 아래와 같이 PolygonShape에 애니메이션 효과가 적용됩니다.

animator