정보 창
정보 창은 마커의 위 또는 지도의 특정 지점에 부가적인 정보를 나타내기 위한 오버레이입니다. 주로 말풍선 형태로 구성되어 텍스트를 표시하는 용도로 사용합니다. 정보 창에 노출될 정보는 어댑터에 의해 지정되므로 정보 창이 열릴 마커의 정보 등을 이용해 동적으로 내용을 갱신할 수 있습니다.
열기 및 닫기
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
프로토콜을 사용한 뷰를 직접 구현할 수도 있습니다.
정보 창은 어댑터 패턴을 사용하므로 정보 창이 열릴 마커나 좌표의 정보를 쉽게 표현할 수 있습니다. 예를 들어, 마커를 탭하면 마커의 속성을 정보 창으로 보여주고자 할 때, 정보 창 객체는 하나만 사용하고 어댑터가 마커의 속성에 따른 정보를 반환하도록 구현하면 됩니다.
다음은 마커를 탭할 때마다 마커에 정보 창을 열고, userInfo
의 tag
를 정보 창에 나타내는 예제입니다.
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);
다음 그림은 정보 창의 앵커를 오른쪽 아래로 지정한 결과입니다.
간격
offsetX
와 offsetY
속성을 이용하면 정보 창과 대상 마커 또는 좌표와의 간격을 지정할 수 있습니다. 간격 속성은 pt 단위이므로 이미지가 불균형해 앵커 지점을 고정할 수 없는 경우 유용합니다. 예를 들어 다음 그림과 같이 오른쪽 아래로부터 왼쪽으로 50pt 떨어진 지점에 꼬리가 달려 있는 이미지를 사용하면 콘텐츠의 크기에 따라 적합한 앵커 지점이 변경됩니다.
이 경우 앵커는 오른쪽 아래를 의미하는 (1, 1)
로 지정하고 offsetX
를 -25
pt로 지정하면 이미지와 대상 지점 간 이격을 해소할 수 있습니다.
다음은 이미지가 늘어나더라도 꼬리가 올바른 위치에 나타나도록 정보 창의 앵커와 오프셋을 지정하는 예제입니다.
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;
다음과 같이 정보 창 이미지의 크기가 바뀌어도 이미지 꼬리가 올바른 위치에 나타나게 됩니다.
불투명
alpha
속성을 이용하면 정보 창의 불투명도를 지정할 수 있습니다. 값의 범위는 0
~1
이며, 0
일 경우 완전히 투명, 1
일 경우 완전히 불투명한 상태가 됩니다. 불투명도가 0
일 경우 visible
이 false
인 경우와 달리 여전히 화면에 나타나 있는 것으로 간주됩니다. 따라서 이벤트 처리의 대상이 됩니다.
다음은 정보 창을 반투명으로 지정하는 예제입니다.
infoWindow.alpha = 0.5
Swift
infoWindow.alpha = 0.5
Objective-C
infoWindow.alpha = 0.5f;
다음 그림은 정보 창을 반투명으로 지정한 결과입니다.