Poi

Poi 개념 및 사용 방법.

Poi는 특정 지점의 정보를 표시할 때 사용합니다. 특정 포인트에 심볼을 지정하여 Badge, Text, Animation 등 다양한 부가적인 효과를 추가하여 커스터마이징 할 수 있습니다.

LabelLayer


LabelLayer는 Poi, WaveText를 담을 수 있는 Layer입니다. Poi를 생성하기 위해서는 먼저 LabelLayer를 생성해야 하고, LabelLayer를 통해서 Poi를 생성할 수 있습니다. LabelLayer는 일종의 폴더처럼 Poi를 관리하고, 레이어에 속한 Poi들을 레이어 속성에 따라 경쟁처리하여 지도에 표시합니다.

LabelLayer 생성하기

LabelLayer는 레이어의 특성을 지정하여 LabelManager를 통해 생성할 수 있습니다. 생성한 LabelLayer는 Manager안에서 관리합니다. LabelLayer를 생성하는 LabelLayerOptions은 아래와 같습니다.

Property Description
layerID layer의 고유 ID. ID는 중복으로 사용할 수 없습니다.
competitionType 다른 Poi와 경쟁하는 방법을 결정합니다. 기본 룰은 타입 순서에 따라 순서가 빠를수록 우선순위가 높습니다.
- none: 경쟁하지 않고 겹쳐서 그려집니다.
- upper: 자신보다 우선순위가 높은 Poi와 경쟁합니다. 상위 Poi에게 우선권이 있으므로 상위 Poi와 겹쳐질경우 그려지지 않습니다.
- same: 자신과 같은 우선순위를 가진 Poi와 경쟁합니다. 이때 경쟁의 기준은 orderType에 따라 결정됩니다.
- lower: 자신보다 우선순위가 낮은 Poi와 경쟁합니다. 상위 Poi에 우선권이 있으므로 자신이 그려진 위치에 upper 속성을 가진 Poi는 그려지지 않습니다.
- background: 최적화를 위해 경쟁 없이 배경처럼 뒤쪽에 그려집니다.
competitionUnit 경쟁하는 단위를 결정합니다.
- poi: Symbol과 Text 모두 경쟁을 통과해야 그려집니다.
- symbolFirst: Symbol만 경쟁의 기준이 됩니다. 문자열은 경쟁에서 통과하지 못하는 경우 심볼만 그려집니다.
orderType competitionType이 same일 때 경쟁하는 기준이 됩니다.
- rank: 각 Poi별로 가지고 있는 rank 속성에 따라 rank값이 높을수록 높은 우선순위를 갖습니다.
- closerFromLeftBottom: 화면 왼쪽 하단과 거리가 가까울수록 높은 우선순위를 갖습니다.
zOrder 레이어의 렌더링 우선순위를 정의합니다. 이 때 렌더링 우선순위는 레이어의 내부가 아닌 여러개의 LabelLayer간의 렌더링 우선순위를 의미합니다.
즉, zOrder가 0인 LabelLayer의 Poi는 zOrder가 1인 LabelLayer에 속한 Poi보다 뒤에 그려집니다.

특정 목적을 가진 Poi끼리 묶어서 하나의 LabelLayer에 넣고, 한꺼번에 Layer자체를 표시하거나, 숨길수도 있습니다. 레이어를 지우면 그 안에 속하는 Poi들도 모두 제거됩니다.

LabelLayer는 기본적으로 사용자가 생성한 LabelLayer끼리 렌더링 우선순위를 API단에서 조절할 수 있습니다. 또한 사용자 Poi가 아닌 지도 내부에 기본적으로 표시되는 Poi도 엔진 내부적으로 정의된 LabelLayer이기 때문에, 렌더링 우선순위를 조절할 수 있습니다. 단, 다른 종류의 View object layer(Shape, Route 등)과는 렌더링 우선순위를 조절할 수 없습니다.

PoiStyle


Poi가 어떻게 표시될지를 정하기 위해 PoiStyle을 사용합니다. PoiStyle은 LabelManager를 통해 생성할 수 있으며, 같은 styleID로는 Overwrite하지 않으므로 중복된 styleID로 추가할 수 없습니다. PoiStyle은 Symbol과 Badge를 정의하는 IconStyle텍스트가 어떻게 표출될지 결정하는 TextLineStyle로 구분할 수 있습니다.

PoiStyle은 한 개 이상의 레벨별 스타일(PerLevelPoiStyle)로 구성됩니다. 각 레벨별 스타일을 통해서 레벨마다 Poi가 어떻게 그려질것인지를 지정합니다. 레벨별 스타일은 PerLevelStyle에 지정한 레벨부터 그려지기 시작합니다.

PerLevelPoiStyle

위 그림의 경우, 하나의 PoiStyle에 각각 0레벨, 5레벨, 15레벨로 PerLevelStyle이 지정되어 있으므로 0-4레벨까지는 PerLevelStyle1, 5-14까지는 PerLevlStyle2, 15부터는 PerLevelStyle3으로 그려집니다.

IconStyle

Poi의 IconStyle은 Symbol, Badge, AnchorPoint, TransitionType 4가지 종류로 구성되어 있습니다.

PoiIconStyle

Description
symbol Poi에 사용할 심볼을 지정합니다. 실제 Poi의 영역으로 인식되어 탭 이벤트나 경쟁을 처리하는 범위로 사용됩니다.
anchorPoint Poi가 그려지는 지점을 지정합니다.
badge Poi에 추가하는 일종의 부가적인 데코레이션입니다. PoiBadge는 아래와 같은 구성을 가지고 있습니다.

Property Description
badgeID Poi에서 특정 badge를 add/remove & show/hide 할 때 고유 식별자로 사용됩니다.
offset Poi 내부에서 Badge가 위치할 Offset을 결정합니다. CGPoint 타입을 사용합니다.


심볼 이미지를 기준으로 좌상단이 (0,0)이고 중앙이 (0.5, 0.5)인 정규화 좌표계를 이룹니다. 이를 바탕으로 badge의 offset을 설정할 수 있습니다.
image badge의 image. 사이즈를 별도로 지정하지 않는 경우 원본 크기로 그려집니다.
zOrder Badge간의 렌더링 우선순위. zOrder를 조절하여 특정 Badge간의 배치 순서를 지정할 수 있습니다.
transitionType Poi 심볼이 나타날 때 / 사라질 때 간단한 애니메이션 타입을 지정할 수 있습니다.
- TransitionTypeNone: 심볼이 나타나거나 사라질 때 애니메이션 효과를 지정하지 않습니다.
- TransitionTypeAlpha: 심볼이 나타나거나 사라질 때 알파값을 조절해서 FadeIn/Out 효과를 줍니다.
- TransitionTypeScale: 심볼이 나타나거나 사라질 때 심볼이 확대/축소되는 효과를 줄 수 있습니다.

또한, Badge의 경우 Poi 객체마다 적용되는 BadgeStyle에 빌트인되어있는 In-Style Badge가 있습니다. 개별 Poi마다 다른 Badge를 표시하고자 하는경우에는 Poi에 있는 Badge를, Poi에 일괄적으로 똑같은 Badge를 추가할땐 In-Style badge를 사용하는것을 권장합니다. Poi 객체에는 Badge를 컨트롤하는 인터페이스가 크게 2가지 종류가 있습니다. In-Style Badge를 컨트롤 하는것과, Poi에 붙는 Badge를 컨트롤 하는 인터페이스가 있습니다. 이 때, Style에 추가된 Badge는 In-Style Badge 관련 함수로만 컨트롤이 가능합니다. 마찬가지로, Poi에 추가된 Badge는 showBadge(), hideBadge()등의 함수로만 컨트롤이 가능합니다.

badges

아래 예제는 위와 같은 형태로 빨간색의 In-Style Badge와 초록색의 PoiBadge를 추가하는 예제입니다.

    // Poi생성을 위한 LabelLayer 생성
    func createLabelLayer() {
        let view = mapController?.getView("mapview") as! KakaoMap
        let manager = view.getLabelManager()
        let layerOption = LabelLayerOptions(layerID: "PoiLayer", competitionType: .none, competitionUnit: .symbolFirst, orderType: .rank, zOrder: 0)
        let _ = manager.addLabelLayer(option: layerOption)
    }
    
    // Poi 표시 스타일 생성
    func createPoiStyle() {
        let view = mapController?.getView("mapview") as! KakaoMap
        let manager = view.getLabelManager()
        
        // PoiBadge는 스타일에도 추가될 수 있다. 이렇게 추가된 Badge는 해당 스타일이 적용될 때 함께 그려진다.
        let noti1 = PoiBadge(badgeID: "badge1", image: UIImage(named: "noti.png"), offset: CGPoint(x: 0.9, y: 0.1), zOrder: 0)
        let iconStyle1 = PoiIconStyle(symbol: UIImage(named: "pin_green.png"), anchorPoint: CGPoint(x: 0.0, y: 0.5), badges: [noti1])
        let noti2 = PoiBadge(badgeID: "badge2", image: UIImage(named: "noti2.png"), offset: CGPoint(x: 0.9, y: 0.1), zOrder: 0)
        let iconStyle2 = PoiIconStyle(symbol: UIImage(named: "pin_red.png"), anchorPoint: CGPoint(x: 0.0, y: 0.5), badges: [noti2])
    
        // 5~11, 12~21 에 표출될 스타일을 지정한다.
        let poiStyle = PoiStyle(styleID: "PerLevelStyle", styles: [
            PerLevelPoiStyle(iconStyle: iconStyle1, level: 5),
            PerLevelPoiStyle(iconStyle: iconStyle2, level: 12)
        ])
        manager.addPoiStyle(poiStyle)
    }
    
    func createPois() {
        let view = mapController?.getView("mapview") as! KakaoMap
        let manager = view.getLabelManager()
        let layer = manager.getLabelLayer(layerID: "PoiLayer")
        let poiOption = PoiOptions(styleID: "PerLevelStyle")
        poiOption.rank = 0
        
        let poi1 = layer?.addPoi(option:poiOption, at: MapPoint(longitude: 127.108678, latitude: 37.402001))
        // Poi 개별 Badge추가. 즉, 아래에서 생성된 Poi는 Style에 빌트인되어있는 badge와, Poi가 개별적으로 가지고 있는 Badge를 갖게 된다.
        let badge = PoiBadge(badgeID: "noti", image: UIImage(named: "noti3.png")!, offset: CGPoint(x: 0, y: 0), zOrder: 1)
        poi1?.addBadge(badge)
        poi1?.show()
        poi1?.showBadge(badgeID: "noti")
    }

TextLineStyle

Poi의 TextLineStyle은 TextStyle, TextLayout, TransitionType으로 구성되어 있습니다.

Property Description
TextStyle Poi에 표시되는 텍스트의 font size, color, 외곽선 두께 및 color를 지정합니다.
TextLayout Poi를 기준으로 텍스트가 어디에 위치할 지 지정합니다.
TransitionType Poi Text가 나타날 때 / 사라질 때 간단한 애니메이션 타입을 지정할 수 있습니다.
- TransitionTypeNone: Text가 나타나거나 사라질 때 애니메이션 효과를 지정하지 않습니다.
- TransitionTypeAlpha: Text가 나타나거나 사라질 때 알파값을 조절해서 FadeIn/Out 효과를 줍니다.
- TransitionTypeScale: Text가 나타나거나 사라질 때 확대/축소되는 효과를 줄 수 있습니다.

TextLineStyle은 IconStyle과 다르게, 하나의 스타일에 여러개의 TextLineStyle을 추가할 수 있습니다. 예를들어, 하나의 Poi에 2개의 텍스트를 추가해야하고, 각 텍스트마다 다른 TextLineStyle로 출력되어야 하는 경우 PoiStyle에 IconStyle과 2개의 TextLineStyle을 지정하면 텍스트마다 다른 스타일을 줄 수 있습니다.

TextLineStyle

위 그림의 경우, PoiStyle은 붉은색 별 모양의 symbol을 갖는 iconStyle과 2개의 TextLineStyle을 갖게 됩니다. 각각의 텍스트 스타일 지정은 인덱스로 지정할 수 있습니다.

TextStyle을 통해서 Poi에 표시되는 텍스트의 색깔, 외곽선 스타일, 폰트 등 스타일을 지정할 수 있습니다. TextStyle의 프로퍼티는 아래와 같습니다.

Property Description
fontSize font 크기
fontColor font 색깔
strokeThickness font 외곽선의 두께
strokeColor font 외곽선의 색깔
font 사용할 font 이름. 별도로 지정하지 않는 경우 엔진의 기본 폰트인 Noto Sans KR Medium을 사용
charSpace 자간. 0~4 사이값을 가짐. 기본값은 0
lineSpace 행간. 1.0~2.0 사이값을 가짐. 기본값은 1.0
aspectRatio 장평. 0.5~2.0 사이의 값을 가짐. 기본값은 1.0

아래 예제는 표에 나타난대로 PoiStyle의 IconStyle과 TextLineStyle을 이용해서 5 ~ 11레벨과 12 ~ 21레벨에서 다른 스타일로 Poi를 표시하는 예제입니다.

5~11 12~21
textStyle1 textStyle1
    // Poi 생성을 위한 LabelLayer 생성
    func createLabelLayer() {
        let view = mapController?.getView("mapview") as! KakaoMap
        let manager = view.getLabelManager()
        let layerOption = LabelLayerOptions(layerID: "PoiLayer", competitionType: .none, competitionUnit: .symbolFirst, orderType: .rank, zOrder: 10)
        let _ = manager.addLabelLayer(option: layerOption)
    }
    
    // Poi 레벨별 표시 스타일 지정
    func createPoiStyle() {
        let view = mapController?.getView("mapview") as! KakaoMap
        let manager = view.getLabelManager()
        
        // PoiBadge는 스타일에도 추가될 수 있다. 이렇게 추가된 Badge는 해당 스타일이 적용될 때 함께 그려진다.
        let noti1 = PoiBadge(badgeID: "badge1", image: UIImage(named: "noti.png"), offset: CGPoint(x: 0.9, y: 0.1), zOrder: 0)
        let iconStyle1 = PoiIconStyle(symbol: UIImage(named: "pin_green.png"), anchorPoint: CGPoint(x: 0.0, y: 0.5), badges: [noti1])
        let noti2 = PoiBadge(badgeID: "badge2", image: UIImage(named: "noti2.png"), offset: CGPoint(x: 0.9, y: 0.1), zOrder: 0)
        let iconStyle2 = PoiIconStyle(symbol: UIImage(named: "pin_red.png"), anchorPoint: CGPoint(x: 0.0, y: 0.5), badges: [noti2])
    
        // text Style 지정
        let red = TextStyle(fontSize: 20, fontColor: UIColor.white, strokeThickness: 2, strokeColor: UIColor.red)
        let blue = TextStyle(fontSize: 20, fontColor: UIColor.white, strokeThickness: 2, strokeColor: UIColor.blue)
        
        // PoiTextStyle 생성
        let textStyle1 = PoiTextStyle(textStyles: [
            PoiTextLineStyle(textStyle: red, textLayout: .bottom)
        ])
        let textStyle2 = PoiTextStyle(textStyles: [
            PoiTextLineStyle(textStyle: blue, textLayout: .bottom)
        ])
        
        let poiStyle = PoiStyle(styleID: "PerLevelStyle", styles: [
            PerLevelPoiStyle(iconStyle: iconStyle1, textStyle: textStyle1, level: 5),
            PerLevelPoiStyle(iconStyle: iconStyle2, textStyle: textStyle2, level: 12)
        ])
        manager.addPoiStyle(poiStyle)
    }
    
    func createPois() {
        let view = mapController?.getView("mapview") as! KakaoMap
        let manager = view.getLabelManager()
        let layer = manager.getLabelLayer(layerID: "PoiLayer")
        
         // poi생성 옵션. 이 Poi가 표시될 스타일의 styleID를 지정한다.
        let poiOption = PoiOptions(styleID: "PerLevelStyle")
        poiOption.rank = 0
        
        // poiText추가. 텍스트는 PoiStyle에서 추가했던 TextLineStyle의 인덱스를 사용한다.
        // 5~11레벨에서는 perLevelStyle1 에 정의되어있는 textLineStyle을 사용하고
        // 12~21레벨에서는 perLevelStyle2에 정의되어있는 textLineStyle을 사용한다.
        poiOption.addText(PoiText(text: "testPoi", styleIndex: 0))
        let poi1 = layer?.addPoi(option:poiOption, at: MapPoint(longitude: 127.108678, latitude: 37.402001))
        poi1?.show()
    }

changeStyle

새로운 스타일을 생성해서 기존에 표시되고 있던 Poi를 다른 스타일로 변경할 수 있습니다. 위에서 설명한 예제와 같이 바꾸고자 하는 스타일을 LabelManager를 통해서 생성한 후, Poi의 changeStyle()을 호출하면, 변경하고자 하는 스타일로 업데이트 됩니다.

아래 에제는 PoiStyle을 변경하는 예제입니다.

    func createLabelLayer() {
        let view = mapController?.getView("mapview") as! KakaoMap
        let manager = view.getLabelManager()
        let layerOption = LabelLayerOptions(layerID: "PoiLayer", competitionType: .none, competitionUnit: .symbolFirst, orderType: .rank, zOrder: 0)
        let _ = manager.addLabelLayer(option: layerOption)
    }
    
    func createPoiStyle() {
        let view = mapController?.getView("mapview") as! KakaoMap
        let manager = view.getLabelManager()
        
        let noti1 = PoiBadge(badgeID: "badge1", image: UIImage(named: "noti.png"), offset: CGPoint(x: 0.9, y: 0.1), zOrder: 0)
        let iconStyle1 = PoiIconStyle(symbol: UIImage(named: "pin_green.png"), anchorPoint: CGPoint(x: 0.0, y: 0.5), badges: [noti1])
        let perLevelStyle1 = PerLevelPoiStyle(iconStyle: iconStyle1, level: 0)
        let poiStyle1 = PoiStyle(styleID: "customStyle1", styles: [perLevelStyle1])
        
        let noti2 = PoiBadge(badgeID: "badge2", image: UIImage(named: "noti2.png"), offset: CGPoint(x: 0.9, y: 0.1), zOrder: 0)
        let iconStyle2 = PoiIconStyle(symbol: UIImage(named: "pin_red.png"), anchorPoint: CGPoint(x: 0.0, y: 0.5), badges: [noti2])
        let perLevelStyle2 = PerLevelPoiStyle(iconStyle: iconStyle2, level: 0)
        let poiStyle2 = PoiStyle(styleID: "customStyle2", styles: [perLevelStyle2])
        
        manager.addPoiStyle(poiStyle1)
        manager.addPoiStyle(poiStyle2)
    }
    
    func createPois() {
        let view = mapController?.getView("mapview") as! KakaoMap
        let manager = view.getLabelManager()
        let layer = manager.getLabelLayer(layerID: "PoiLayer")
        let poiOption = PoiOptions(styleID: "customStyle1", poiID: "poi1")
        poiOption.rank = 0
        
        let poi1 = layer?.addPoi(option:poiOption, at: MapPoint(longitude: 127.108678, latitude: 37.402001))
        poi1?.show()
    }
    
    @IBAction func changeButtonClicked(_ sender: Any) {
        let view = mapController?.getView("mapview") as! KakaoMap
        let manager = view.getLabelManager()
        let layer = manager.getLabelLayer(layerID: "PoiLayer")
        let poi = layer?.getPoi(poiID: "poi1")
        poi?.changeStyle(styleID: "customStyle2")
    }

changeTextAndStyle

새로운 스타일을 생성해서 기존에 표시되고 있던 Poi를 다른 스타일로 변경하면서 Poi에 표시되고 있는 text를 함께 바꿀 수 있습니다. 아래 예제는 추가한 Poi의 text와 style을 함께 업데이트 하는 예제입니다.


    func createLabelLayer() {
        let view = mapController?.getView("mapview") as! KakaoMap
        let manager = view.getLabelManager()
        let layerOption = LabelLayerOptions(layerID: "PoiLayer", competitionType: .none, competitionUnit: .symbolFirst, orderType: .rank, zOrder: 0)
        let _ = manager.addLabelLayer(option: layerOption)
    }
    
    func createPoiStyle() {
        let view = mapController?.getView("mapview") as! KakaoMap
        let manager = view.getLabelManager()
        
        let badge1 = PoiBadge(badgeID: "badge1", image: UIImage(named: "noti.png"), offset: CGPoint(x: 0.9, y: 0.1), zOrder: 0)
        let iconStyle1 = PoiIconStyle(symbol: UIImage(named: "pin_green.png"), anchorPoint: CGPoint(x: 0.0, y: 0.5), badges: [badge1])
        let text1 = PoiTextLineStyle(textStyle: TextStyle(fontSize: 20, fontColor: UIColor.white, strokeThickness: 2, strokeColor: UIColor.green), textLayout: .center)
        let textStyle1 = PoiTextStyle(textStyles: [text1])
        let poiStyle1 = PoiStyle(styleID: "customStyle1", styles: [
            PerLevelPoiStyle(iconStyle: iconStyle1, textStyle: textStyle1, level: 0)
        ])
        
        let badge2 = PoiBadge(badgeID: "badge2", image: UIImage(named: "noti2.png"), offset: CGPoint(x: 0.9, y: 0.1), zOrder: 0)
        let iconStyle2 = PoiIconStyle(symbol: UIImage(named: "pin_red.png"), anchorPoint: CGPoint(x: 0.0, y: 0.5), badges: [badge2])
        let text2 = PoiTextLineStyle(textStyle: TextStyle(fontSize: 20, fontColor: UIColor.white, strokeThickness: 2, strokeColor: UIColor.red), textLayout: .center)
        let textStyle2 = PoiTextStyle(textStyles: [text2])
        let poiStyle2 = PoiStyle(styleID: "customStyle2", styles: [
            PerLevelPoiStyle(iconStyle: iconStyle2, textStyle: textStyle2, level: 0)
        ])
        
        manager.addPoiStyle(poiStyle1)
        manager.addPoiStyle(poiStyle2)
    }
    
    func createPois() {
        let view = mapController?.getView("mapview") as! KakaoMap
        let manager = view.getLabelManager()
        let layer = manager.getLabelLayer(layerID: "PoiLayer")
        let poiOption = PoiOptions(styleID: "customStyle1", poiID: "poi1")
        poiOption.rank = 0
        poiOption.addText(PoiText(text: "POI Text", styleIndex: 0))
        
        let poi1 = layer?.addPoi(option:poiOption, at: MapPoint(longitude: 127.108678, latitude: 37.402001))
        poi1?.show()
    }
    
    @IBAction func changeButtonClicked(_ sender: Any) {
        let view = mapController?.getView("mapview") as! KakaoMap
        let manager = view.getLabelManager()
        let layer = manager.getLabelLayer(layerID: "PoiLayer")
        let poi = layer?.getPoi(poiID: "poi1")
        
        // 바꾸고자 하는 PoiText로 업데이트한다.
        // 이때 PoiText가 사용하는 styleIndex는 바꿀 스타일에 매치된다.
        poi?.changeTextAndStyle(texts: [PoiText(text: "Changed POI Text", styleIndex: 0)], styleID: "customStyle2")
    }

removePoiStyle

추가한 PoiStyle을 더이상 사용하지 않을 때, PoiStyle을 삭제합니다.

    func removePoiStyles() {
        let view = mapController?.getView("mapview") as! KakaoMap
        let manager = view.getLabelManager()
        manage.removePoiStyle("customStyle1")
    }

PoiOptions


Poi는 사용자가 직접 생성할 수 없습니다. LabelManager를 통해 생성한 LabelLayer에 아래와 같은 addPoi(s)를 호출할 때 PoiOptions 생성 옵션을 넘기면 API 내부적으로 생성한 Poi객체를 받아올 수 있습니다.

// 첫번째 스타일 적용한 Poi생성
let poiOption = PoiOptions(styleID: "customStyle1", poiID: "poi1")
        
let poi1 = layer?.addPoi(option:poiOption, at: MapPoint(longitude: 127.108678, latitude: 37.402001))

PoiOptions의 속성은 아래와 같습니다. 각 property를 지정하여 Poi를 다양하게 생성할 수 있습니다.

Property Description
poiID Poi의 고유 ID. 같은 Layer안에서 중복된 ID를 가질 수 없습니다. 별도로 지정하지 않는 경우 API내부적으로 고유 ID를 부여하여 생성합니다.
styleID Poi가 사용할 styleID. Poi를 생성하는 시점에서 style은 미리 생성되어 있어야 합니다.
rank Poi의 렌더링 우선순위. Layer정의에 따라 Poi가 먼저 그려질지 경쟁하는 기준이 됩니다.
clickable Poi의 클릭가능 여부. default는 false로 세팅됩니다.
transformType Poi의 카메라에 따른 회전 및 틸팅여부를 지정합니다. Poi 생성 후에는 변경할 수 없습니다. 총 4가지 타입이 존재합니다. 심볼과 텍스트가 같이 존재하는 경우 텍스트는 default type으로 동작하고 심볼에만 지정된 타입이 적용됩니다. 텍스트만 존재하는 경우에는 텍스트가 지정된 타입으로 동작합니다.
- PoiTransformTypeDefault: 카메라가 회전하는 방향대로 Poi가 따라 회전합니다.
- PoiTransformTypeAbsoluteRotation: 카메라의 회전값이 Poi에 반영되지 않아 항상 특정한 방향을 가리킵니다.
- PoiTransformTypeKeepUpright: 카메라의 회전값이 Poi에 반영되지 않아 항상 특정한 방향을 가리키지만, Poi가 뒤집히면 다시 +180만큼 회전시켜서 똑바로 유지합니다.
- PoiTransformTypeAbsoluteRotationDecal: Decal타입처럼 바닥에 붙지만 특정 방향을 가질 수 있는 타입입니다.
- PoiTransformTypeDecal: 바닥에 붙어 있는 형태로 그려지는 타입입니다.
texts Poi에 추가되는 텍스트 배열. Multi라인으로 추가 가능하며, 각 라인별로 사용할 스타일 인덱스를 지정하여 다르게 표시할 수 있습니다.

LabelLayer에서 Poi를 추가하는 함수는 아래와 같이 3가지 형태가 존재하는데, 아래와 같은 사용을 권장합니다.

  • addPoi(option:at:)-> Poi : 하나의 Poi만 생성할 때 사용합니다.
  • addPois(option:at:) -> [Poi] : 똑같은 option을 가지고 위치만 다른 여러개의 Poi를 생성할 때 사용합니다.
  • addPois(options:at:) -> [Poi] : 각각 다른 option을 가지는 여러개의 Poi를 한꺼번에 생성합니다. 이때 option 배열의 사이즈는 위치를 담은 배열의 사이즈와 동일해야 합니다.

Poi Properties


LabelLayer를 통해 생성된 Poi는 아래와 같은 종류의 Property를 가지고 있습니다.

Property Description
layerID Poi가 속한 layer의 ID
itemID Poi의 ID
rank Poi의 rank. 값을 새로 설정하면, rank값이 업데이트 됩니다.
clickable Poi의 클릭 가능 여부. 값을 새로 설정하면, clickable 값이 업데이트 되고 Poi의 클릭 가능 여부가 변경됩니다.
position Poi의 position. 값을 새로 설정하면, Poi의 position이 업데이트 되고 해당 위치에 그려집니다.
orientation Poi의 회전각(radian). 값을 새로 설정하면, Poi의 orientation이 업데이트 되고 해당 값만큼 Poi가 회전합니다.
isShow Poi가 현재 뷰에 표시되고 있는지 여부
userObject Poi의 UserObject

Poi Animation


Poi에는 총 3가지 애니메이션이 존재합니다.

  • Transition: PoiOptions으로 간단하게 지정할 수 있는 Transition. Poi가 나타나고 사라질 때 alpha / scale이 조정되면서 애니메이션 효과를 줍니다.
  • moveAt/rotateAt: 이동/회전을 하는 과정을 보여주는 애니메이션 효과 입니다.
  • Animator: 여러개의 Poi에 좀 더 복잡한 애니메이션 효과를 줄 수 있습니다. 현재까지는 DropAnimationEffect만 존재합니다.

이동 및 회전 애니메이션

Poi객체에는 4가지 종류의 이동 및 회전 애니메이션이 존재합니다.

  • moveAt(_:duration:): 지정한 위치로 duration동안 Poi가 이동합니다.
  • rotateAt(_:duration:): 지정한 회전값만큼 duration동안 Poi가 회전합니다.
  • moveOnPath(_:duration:cornerRadius:jumpThreshold:): 지정한 Path를 duration동안 Poi가 이동합니다.
  • moveAndRotateOnPath(_:baseRadian:duration:cornerRadius:jumpThreshold:): 지정한 Path를 duration동안 Poi가 이동하고, Path각도에 따라 Poi가 같이 회전하며 이동합니다.

Sharing Transform


Poi의 현재 위치 및 회전값을 다른 Poi 혹은 Shape와 공유할 수 있습니다. 즉, Poi가 움직이거나 회전하면 그와 함께 다른 Poi나 Shape를 움직이게 할 수 있습니다.

Poi 클래스 내부 shareTransformWith 를 사용하여 Poi와 Shape, 혹은 Poi와 Poi의 이동 및 회전을 동기화 시킬 수 있습니다. transform을 공유하기 시작하면 remove를 수행하기전까지는 함께 움직이고 회전합니다. 아래 예제 코드는 Poi type으로 생성한 CurrentPositionMarker와 CurrentPosition의 방향을 나타내는 Arrow형태의 Poi간의 Transform sharing 예제입니다.

    func createPois() {
        let view = mapController?.getView("mapview") as! KakaoMap
        let manager = view.getLabelManager()
        let positionLayer = manager.getLabelLayer(layerID: "PositionPoiLayer")
        let directionLayer = manager.getLabelLayer(layerID: "DirectionPoiLayer")
        
        // 현위치마커의 몸통에 해당하는 POI
        let poiOption = PoiOptions(styleID: "positionPoiStyle", poiID: "PositionPOI")
        poiOption.rank = 1
        poiOption.transformType = .decal    //화면이 기울여졌을 때, 지도를 따라 기울어져서 그려지도록 한다.
        let position: MapPoint = MapPoint(longitude: 127.108678, latitude: 37.402001)
        
        _currentPositionPoi = positionLayer?.addPoi(option:poiOption, at: position)
        
        // 현위치마커의 방향표시 화살표에 해당하는 POI
        let poiOption2 = PoiOptions(styleID: "directionArrowPoiStyle", poiID: "DirectionArrowPOI")
        poiOption2.rank = 3
        poiOption2.transformType = .absoluteRotationDecal
        
        _currentDirectionArrowPoi = positionLayer?.addPoi(option:poiOption2, at: position)
        
        // 현위치마커의 부채꼴모양 방향표시에 해당하는 POI
        let poiOption3 = PoiOptions(styleID: "directionPoiStyle", poiID: "DirectionPOI")
        poiOption3.rank = 2
        poiOption3.transformType = .decal
        
        _currentDirectionPoi = directionLayer?.addPoi(option:poiOption3, at: position)
        
        _currentPositionPoi?.shareTransformWithPoi(_currentDirectionArrowPoi!)  //몸통이 방향표시와 위치 및 방향을 공유하도록 지정한다. 몸통 POI의 위치가 변경되면 방향표시 POI의 위치도 변경된다. 반대는 변경안됨.
        _currentDirectionArrowPoi?.shareTransformWithPoi(_currentDirectionPoi!) //방향표시가 부채꼴모양과 위치 및 방향을 공유하도록 지정한다.
    }

Sharing Position


Poi의 현재 위치만을 다른 Poi와 공유할 수 있습니다. 즉, Poi가 움직이면 다른 Poi가 쫓아다니는 형태를 구현할 수 있습니다.

Poi 클래스 내부 sharePositionWithPoi API를 사용하여 Poi와 Poi의 이동을 동기화 시킬 수 있습니다. position을 공유하기 시작하면 removeSharePositionWithPoi를 수행하기전까지는 함께 움직입니다. 두개의 Poi가 위치를 공유하며 함께 움직이는 Poi를 구현한 예제입니다.

func createPois() {
    let view = mapController?.getView("mapview") as! KakaoMap
    let manager = view.getLabelManager()
    let trackingManager = view.getTrackingManager() // POI를 따라서 카메라를 이동시키기 위한 Manager.
    let layer = manager.getLabelLayer(layerID: "PoiLayer")
    let options = PoiOptions(styleID: "busStyle", poiID: "jejuBus_1")
    options.rank = 0
    options.transformType = .absoluteRotationDecal
    
    // bus Poi 생성
    let bus = layer?.addPoi(option:options, at: pathData()[0])
    bus?.show()
    bus?.moveAndRotateOnPath(pathData(), baseRadian: 0.0, duration: 10000, cornerRadius: 3.0, jumpThreshold: 3.0)   //지정된 경로를 따라 duration동안 이동한다.
    view.moveCamera(CameraUpdate.make(target: pathData()[0], zoomLevel: 15, mapView: view))

    // bus Poi를 따라다닐 Poi생성
    let options2 = PoiOptions(styleID: "poiStyle")
    let poi = layer?.addPoi(option: options2, at: pathData()[0])
    poi?.show()
    
    // bus의 Position을 poi가 따라다니게 함. 위치를 공유하기 시작한다.
    bus?.sharePositionWithPoi(poi!)
    
    trackingManager.startTrackingPoi(bus!)
}