정보 창

정보 창은 마커의 위 또는 지도의 특정 지점에 부가적인 정보를 나타내기 위한 오버레이입니다. 주로 말풍선 형태로 구성되어 텍스트를 표시하는 용도로 사용합니다. 정보 창에 노출될 정보는 어댑터에 의해 지정되므로 정보 창이 열릴 마커의 정보 등을 이용해 동적으로 내용을 갱신할 수 있습니다.

열기 및 닫기

NMFInfoWindow는 일반적인 클래스 객체처럼 생성할 수 있습니다. 정보 창을 열려면 객체를 생성하고 dataSource 속성에 이미지 리소스를 만들기 위한 프로토콜을 지정해야 합니다.

다음은 정보 창 객체를 생성하고 프로토콜을 지정하는 예제입니다.

let infoWindow = NMFInfoWindow()
let dataSource = NMFInfoWindowDefaultTextSource.data()
dataSource.title = "정보 창 내용"
infoWindow.dataSource = dataSource

Swift

let infoWindow = NMFInfoWindow()
let dataSource = NMFInfoWindowDefaultTextSource.data()
dataSource.title = "정보 창 내용"
infoWindow.dataSource = dataSource

Objective-C

NMFInfoWindow *infoWindow = [NMFInfoWindow new];
NMFInfoWindowDefaultTextSource *dataSource = [NMFInfoWindowDefaultTextSource dataSource];
dataSource.title = @"정보 창 내용";
infoWindow.dataSource = dataSource;

이후 -openXXX: 메서드를 호출하면 정보 창이 나타납니다. 정보 창은 지도에 추가되어 있는 마커에 열거나 임의의 좌표에 열 수 있습니다. 정보 창을 마커 위에 열려면 -openWithMarker: 메서드를, 임의의 좌표에 열려면 position 속성을 지정한 후 -openWithMapView: 메서드를 호출합니다. 단, -openXXX: 메서드를 호출하기 전에는 반드시 dataSource를 지정해야 합니다.

다음은 정보 창을 마커에 여는 예제입니다.

infoWindow.open(with: marker)

Swift

infoWindow.open(with: marker)

Objective-C

[infoWindow openWithMarker:marker];

다음 그림은 마커에 정보 창을 추가한 결과입니다.

마커에 정보창을 추가한 모습

다음은 정보 창을 임의의 좌표에 여는 예제입니다.

infoWindow.position = NMGLatLng(lat: 37.5666102, lng: 126.9783881)
infoWindow.open(with: mapView)

Swift

infoWindow.position = NMGLatLng(lat: 37.5666102, lng: 126.9783881)
infoWindow.open(with: mapView)

Objective-C

infoWindow.position = NMGLatLngMake(37.5666102, 126.9783881);
[infoWindow openWithMapView:self.mapView];

다음 그림은 임의의 좌표에 정보 창을 추가한 결과입니다.

임의의 좌표에 정보창을 추가한 모습

-close를 호출하면 정보 창이 닫히고 지도에서 사라집니다.

다음은 정보 창을 닫는 예제입니다.

infoWindow.close()

Swift

infoWindow.close()

Objective-C

[infoWindow close];

정보 창을 임의의 좌표에 열려면 -openWithMapView:-close를 호출하는 대신 다른 오버레이처럼 mapView 속성을 사용할 수도 있습니다. 속성에 지도 객체를 지정하면 -openWithMapView:를 호출한 것과, nil을 지정하면 -close를 호출한 것과 동일한 결과가 나타납니다.

다음은 mapView 속성을 이용해 정보 창을 임의의 좌표에 여는 예제입니다.

infoWindow.position = NMGLatLng(lat: 37.5670135, lng: 126.9783740)
infoWindow.mapView = mapView

Swift

infoWindow.position = NMGLatLng(lat: 37.5670135, lng: 126.9783740)
infoWindow.mapView = mapView

Objective-C

infoWindow.position = NMGLatLngMake(37.5670135, 126.9783740);
infoWindow.mapView = self.mapView;

다음은 mapView 속성을 이용해 정보 창을 닫는 예제입니다.

infoWindow.mapView = nil

Swift

infoWindow.mapView = nil

Objective-C

infoWindow.mapView = nil;

마커 및 지도와 상호작용

정보 창이 마커에 대해 열린 경우 정보 창과 마커 간에는 연관 관계가 형성됩니다. NMFInfoWindow.marker는 정보 창이 열린 마커를, NMFMarker.infowindow는 마커에 열려 있는 정보 창을 반환합니다. 이러한 연관 정보를 사용하면 정보 창을 사용하는 가장 흔한 패턴인 마커를 터치할 때 열고, 마커를 다시 터치하거나 정보 창 바깥 영역, 즉 지도를 터치할 때 닫는 동작을 쉽게 구현할 수 있습니다.

다음은 마커와 정보 창간의 연관 관계와 터치 핸들러를 이용해 이러한 동작을 구현한 예제입니다.

// 지도를 탭하면 정보 창을 닫음
func mapView(_ mapView: NMFMapView, didTapMap latlng: NMGLatLng, point: CGPoint) {
    infoWindow.close()
}

// 마커를 탭하면:
let handler = { [weak self] (overlay: NMFOverlay) -> Bool in
    if let marker = overlay as? NMFMarker {
        if marker.infoWindow == nil {
            // 현재 마커에 정보 창이 열려있지 않을 경우 엶
            self?.infoWindow.open(with: marker)
        } else {
            // 이미 현재 마커에 정보 창이 열려있을 경우 닫음
            self?.infoWindow.close()
        }
    }
    return true
};

marker1.touchHandler = handler
marker2.touchHandler = handler
marker3.touchHandler = handler

Swift

// 지도를 탭하면 정보 창을 닫음
func mapView(_ mapView: NMFMapView, didTapMap latlng: NMGLatLng, point: CGPoint) {
    infoWindow.close()
}

// 마커를 탭하면:
let handler = { [weak self] (overlay: NMFOverlay) -> Bool in
    if let marker = overlay as? NMFMarker {
        if marker.infoWindow == nil {
            // 현재 마커에 정보 창이 열려있지 않을 경우 엶
            self?.infoWindow.open(with: marker)
        } else {
            // 이미 현재 마커에 정보 창이 열려있을 경우 닫음
            self?.infoWindow.close()
        }
    }
    return true
};

marker1.touchHandler = handler
marker2.touchHandler = handler
marker3.touchHandler = handler

Objective-C

// 지도를 탭하면 정보 창을 닫음
- (void)mapView:(NMFMapView *)mapView didTapMap:(NMGLatLng *)latlng point:(CGPoint)point {
    [self.infoWindow close];
}

// 마커를 탭하면:
__block weakSelf = self;
NMFOverlayTouchHandler handler = ^BOOL(NMFOverlay *overlay) {
    NMFMarker *marker = (NMFMarker *)overlay;

    if (marker.infoWindow == nil) {
        // 현재 마커에 정보 창이 열려있지 않을 경우 엶
        [weakSelf.infoWindow openWithMarker:marker];
    } else {
        // 이미 현재 마커에 정보 창이 열려있을 경우 닫음
        [weakSelf.infoWindow close];
    }

    return true;
};

marker1.touchHandler = handler;
marker2.touchHandler = handler;
marker3.touchHandler = handler;

데이터 소스

dataSource 속성을 사용해 정보 창에 대한 데이터 소스 프로토콜을 지정할 수 있습니다. 마커 등 이미지를 사용하는 다른 오버레이와 달리 정보 창에는 이미지를 지정하는 속성이 없습니다. 대신 데이터 소스 속성이 있으며, 이 속성에 지정된 데이터 소스 객체가 정보 창에 나타나야 할 이미지를 반환합니다. -openXXX: 메서드가 호출될 때마다 데이터 소스 메서드가 호출되어 정보 창의 내용이 갱신되며, -invalidate를 호출해 명시적으로 내용을 갱신할 수도 있습니다.

정보 창에 데이터 소스를 지정하는 가장 간단한 방법은 NMFInfoWindowDefaultTextSource를 사용하는 것입니다. NMFInfoWindowDefaultTextSource의 유일한 속성인 title에 정보 창에 나타나야 할 텍스트를 지정하기만 하면 됩니다. 이 데이터소스를 정보 창에 지정하면 기본 말풍선 이미지 내에 지정한 텍스트가 나타납니다.

다음은 NMFInfoWindowDefaultTextSource를 이용하는 예제입니다.

let defaultDataSource = NMFInfoWindowDefaultTextSource.data()
defaultDataSource.title = "정보 창 내용"
infoWindow.dataSource = defaultDataSource

Swift

let defaultDataSource = NMFInfoWindowDefaultTextSource.data()
defaultDataSource.title = "정보 창 내용"
infoWindow.dataSource = defaultDataSource

Objective-C

NMFInfoWindowDefaultTextSource *defaultDataSource = [NMFInfoWindowDefaultTextSource dataSource];
defaultDataSource.title = "정보 창 내용"
infoWindow.dataSource = defaultDataSource;

다음과 같이 "정보 창 내용"이라는 텍스트가 정보 창에 표시됩니다.

정보창에 설정한 텍스트가 나타나는 모습

기본 말풍선 이미지를 사용하지 않으려면 NMFOverlayImageDataSource 프로토콜을 사용한 뷰를 직접 구현할 수도 있습니다.

정보 창은 어댑터 패턴을 사용하므로 정보 창이 열릴 마커나 좌표의 정보를 쉽게 표현할 수 있습니다. 예를 들어, 마커를 탭하면 마커의 속성을 정보 창으로 보여주고자 할 때, 정보 창 객체는 하나만 사용하고 어댑터가 마커의 속성에 따른 정보를 반환하도록 구현하면 됩니다.

다음은 마커를 탭할 때마다 마커에 정보 창을 열고, userInfotag를 정보 창에 나타내는 예제입니다.

let handler = { [weak self] (overlay: NMFOverlay) -> Bool in
    if let marker = overlay as? NMFMarker {
        // 정보 창이 열린 마커의 tag를 텍스트로 노출하도록 반환 
        self?.defaultDataSource.title = marker.userInfo["tag"] as! String
        // 마커를 터치할 때 정보창을 엶
        self?.infoWindow.open(with: marker1)
    }
    return true
};
marker1.userInfo = ["tag": "마커 1"]
marker1.touchHandler = handler
marker2.userInfo = ["tag": "마커 2"]
marker2.touchHandler = handler

Swift

let handler = { [weak self] (overlay: NMFOverlay) -> Bool in
    if let marker = overlay as? NMFMarker {
        // 정보 창이 열린 마커의 tag를 텍스트로 노출하도록 반환 
        self?.defaultDataSource.title = marker.userInfo["tag"] as! String
        // 마커를 터치할 때 정보창을 엶
        self?.infoWindow.open(with: marker1)
    }
    return true
};
marker1.userInfo = ["tag": "마커 1"]
marker1.touchHandler = handler
marker2.userInfo = ["tag": "마커 2"]
marker2.touchHandler = handler

Objective-C

__block weakSelf = self;
NMFOverlayTouchHandler handler = ^BOOL(NMFOverlay *overlay) {
    NMFMarker *marker = (NMFMarker *)overlay;

    // 정보 창이 열린 마커의 tag를 텍스트로 노출하도록 반환 
    weakSelf.defaultDataSource.title = marker.userInfo[@"tag"];
    // 마커를 터치할 때 정보창을 엶
    [weakSelf.infoWindow openWithMarker:marker];
    return true;
};

marker1.userInfo = @{ @"tag" : @"마커 1" };
marker1.touchHandler = handler;
marker2.userInfo = @{ @"tag" : @"마커 2" };
marker2.touchHandler = handler;

다음과 같이 마커를 탭할 때마다 마커의 속성에 따른 정보를 정보 창에 나타냅니다.

마커의 속성에 따른 정보를 반환하는 모습 마커의 속성에 따른 정보를 반환하는 모습

배치

정보 창이 나타날 방향, 이미지의 앵커, 대상 지점과의 간격 등을 지정하면 기본 말풍선 이미지를 사용하지 않더라도 정보가 정확한 위치에 나타나도록 할 수 있습니다.

방향

정보 창은 기본적으로 마커의 위에 배치되나, -openWithMarker:alignType:을 사용하면 배치되는 방향을 변경할 수 있습니다. 위, 아래, 왼쪽, 오른쪽, 각 대각선, 중앙 등 NMFAlignType 객체에 정의된 아홉 곳에 정보 창을 배치할 수 있습니다.

다음은 정보 창을 마커의 오른쪽에 배치하는 예제입니다.

infoWindow.open(with: marker, alignType: NMFAlignType.right)

Swift

infoWindow.open(with: marker, alignType: NMFAlignType.right)

Objective-C

[infoWindow openWithMarker:marker alignType:NMFAlign.right];

다음 그림은 정보 창을 마커의 오른쪽에 배치한 결과입니다.

정보창을 마커의 오른쪽에 배치한 모습

앵커

anchor 속성을 지정하면 이미지가 가리키는 지점과 대상 지점을 일치시킬 수 있습니다. 앵커는 이미지에서 기준이 되는 지점을 의미하는 값으로, 이미지에서 앵커로 지정된 지점이 대상 지점에 위치하게 됩니다. 왼쪽 위가 (0, 0), 오른쪽 아래가 (1, 1)인 비율값으로 표현합니다.

앵커 속성은 기본 배경 이미지를 사용하지 않을 때 유용합니다. 예를 들어 다음 그림과 같이 오른쪽 아래에 꼬리가 달려 있는 이미지를 사용하면, 이미지에서 가리키는 지점은 오른쪽 아래이지만 정보 창은 중앙 아래를 기준으로 대상 지점에 붙어 있으므로 이미지와 정보 창의 위치 간에 이격이 발생합니다.

이미지와 정보 창의 좌표 간 이격이 발생한 모습

이 경우 앵커를 오른쪽 아래를 의미하는 (1, 1)로 지정하면 이미지와 대상 지점 간 이격을 해소할 수 있습니다.

다음은 정보 창의 앵커를 오른쪽 아래로 지정하는 예제입니다.

infoWindow.anchor = CGPoint(x: 1, y: 1)

Swift

infoWindow.anchor = CGPoint(x: 1, y: 1)

Objective-C

infoWindow.anchor = CGPointMake(1, 1);

다음 그림은 정보 창의 앵커를 오른쪽 아래로 지정한 결과입니다.

정보창의 앵커를 오른쪽 아래로 지정한 모습

간격

offsetXoffsetY 속성을 이용하면 정보 창과 대상 마커 또는 좌표와의 간격을 지정할 수 있습니다. 간격 속성은 pt 단위이므로 이미지가 불균형해 앵커 지점을 고정할 수 없는 경우 유용합니다. 예를 들어 다음 그림과 같이 오른쪽 아래로부터 왼쪽으로 50pt 떨어진 지점에 꼬리가 달려 있는 이미지를 사용하면 콘텐츠의 크기에 따라 적합한 앵커 지점이 변경됩니다.

앵커 지점을 고정할 수 없는 경우 1 앵커 지점을 고정할 수 없는 경우 2

이 경우 앵커는 오른쪽 아래를 의미하는 (1, 1)로 지정하고 offsetX-25pt로 지정하면 이미지와 대상 지점 간 이격을 해소할 수 있습니다.

다음은 이미지가 늘어나더라도 꼬리가 올바른 위치에 나타나도록 정보 창의 앵커와 오프셋을 지정하는 예제입니다.

infoWindow.anchor = CGPoint(x: 1, y: 1)
infoWindow.offsetX = -25

Swift

infoWindow.anchor = CGPoint(x: 1, y: 1)
infoWindow.offsetX = -25

Objective-C

infoWindow.anchor = CGPointMake(1, 1);
infoWindow.offsetX = -25;

다음과 같이 정보 창 이미지의 크기가 바뀌어도 이미지 꼬리가 올바른 위치에 나타나게 됩니다.

x축 오프셋을 지정한 모습 1 x축 오프셋을 지정한 모습 2

불투명

alpha 속성을 이용하면 정보 창의 불투명도를 지정할 수 있습니다. 값의 범위는 0~1이며, 0일 경우 완전히 투명, 1일 경우 완전히 불투명한 상태가 됩니다. 불투명도가 0일 경우 visiblefalse인 경우와 달리 여전히 화면에 나타나 있는 것으로 간주됩니다. 따라서 이벤트 처리의 대상이 됩니다.

다음은 정보 창을 반투명으로 지정하는 예제입니다.

infoWindow.alpha = 0.5

Swift

infoWindow.alpha = 0.5

Objective-C

infoWindow.alpha = 0.5f;

다음 그림은 정보 창을 반투명으로 지정한 결과입니다.

정보창을 반투명으로 지정한 모습

results matching ""

    No results matching ""