로드뷰

KakaoMap에서 로드뷰 사용하기.

로드뷰는 도로위에서 실제 도로 주변의 모습을 360도 전방위로 촬영한 파노라마 사진을 보여주는 서비스입니다. 로드뷰 기능을 사용하기 위해서는 별도의 협의가 필요합니다.

로드뷰 표시하기


로드뷰를 보여주기 위해서는 먼저 ViewInfo중 RoadviewInfo 클래스를 이용하여 Roadview를 생성해야 합니다. Roadview 클래스를 이용하여 보여주고자 하는 로드뷰 촬영 지점(로드뷰 스팟)에 대한 정보를 서버에 요청해야 합니다. 이 요청이 성공하는 경우, 로드뷰 스팟에 대한 정보를 수신하여 로드뷰를 보여줍니다.

각각의 로드뷰 스팟은 좌표값과 panoID라는 고유 식별자를 가집니다. 서버에 로드뷰 스팟에 대한 정보를 요청할 때, panoID를 이용하여 요청하거나, 좌표값을 이용하여 주변 로드뷰 스팟을 검색하도록 요청할 수 있습니다. panoID는 null로 요청할 수 있으나, 요청하는 좌표값은 항상 있어야합니다. panoID가 null인경우, 반경 100m까지 검색하고 결과가 없을 경우 400m로 확장하여 한번 더 검색합니다. panoID와 position을 함께 요청할 경우 panoID에 대한 데이터가 있을 겅우 해당 데이터를 사용하고, 없을 경우 position을 기준으로 반경 100m까지 검색합니다. 반경으로 검색하게 되는 경우 검색 중심 position에서 가장 가까운 지점의 데이터를 사용합니다.

아래 코드는 Roadview를 생성하여 로드뷰를 보여주는 예제 코드입니다.

override func addViews() {
	let defaultPosition: MapPoint = MapPoint(longitude: 126.978365, latitude: 37.566691)
	let roadviewInfo: RoadviewInfo = RoadviewInfo(viewName: "roadview", viewInfoName: "roadview", enabled: true)
	//로드뷰 추가.
	mapController?.addView(roadviewInfo)
}

func addViewSucceeded(_ viewName: String, viewInfoName: String) {
    print("Roadview OK")
    requestRoadview()
}
    
func requestRoadview() {
	let view = mapController?.getView("roadview") as! Roadview
	let defaultPosition: MapPoint = MapPoint(longitude: 126.978365, latitude: 37.566691)
	//좌표로 로드뷰 요청. panoID를 알 경우, panoID를 지정할 수 있다. panoID가 지정되면 해당 panoID로 먼저 검색한 뒤 없으면 좌표로 검색한다.
	view.requestRoadview(position: defaultPosition, panoID: nil)
}

RoadviewLookAt

로드뷰에 진입할 때, 로드뷰가 보는 방향을 지정할 수 있습니다. 로드뷰를 요청할 때, RoadviewLookAt을 지정하여 바라볼 방향 혹은 바라볼 위치를 지정하면 로드뷰 진입 시 해당 LookAt을 보게 됩니다.

    func requestRoadview() {
        let view = mapController?.getView("roadview") as! Roadview
        let defaultPosition: MapPoint = MapPoint(longitude: 126.978365, latitude: 37.566691)
        
        // RoadviewLookAt지정
        // 요청한 로드뷰로 진입할 때 화면에 표시될 때 바라볼 방향(pan, tilt) 혹은 바라볼 위치(position)를 지정할 수 있다.
        let lookAt = RoadviewLookAt(pan: 0.5, tilt: 0.2)
        
        //좌표로 로드뷰 요청. panoID를 알 경우, panoID를 지정할 수 있다. panoID가 지정되면 해당 panoID로 먼저 검색한 뒤 없으면 좌표로 검색한다.
        // 로드뷰를 요청할 때, RoadviewLookAt를 함께 전달한다.
        view.requestRoadview(position: defaultPosition, panoID: nil, markers: nil, lookAt: lookAt)
    } 

PanoramaMarker

로드뷰를 요청할 때, 로드뷰 위 특정 위치에 PanoramaMarker를 띄울 수 있습니다. 파노라마 마커는 position혹은 pan/tilt 두 가지 타입으로 지정할 수 있습니다. position는 특정 지점을 표시할 때 사용하며, 좌표값을 이용하여 특정 지점에 마커를 올릴 수 있습니다. pan/tilt는 특정 지점이 아닌 pan과 tilt값만을 이용하여 특정 방향을 표시할 때 사용합니다. 로드뷰를 요청할 때 panoID 및 position과 함께 마커를 함께 전달하면, 로드뷰가 표시될 때 마커가 같이 표시됩니다.

아래 예제는 로드뷰와 함께 PanoramaMarker를 표시하는 예제입니다.

    @IBAction func requestRoadview(_ sender: AnyObject) {
        let mapView: KakaoMap? = mapController?.getView("mapview") as? KakaoMap
        let roadView: Roadview? = mapController?.getView("roadview") as? Roadview
        
        let position = mapView!.getPosition(CGPoint(x: mapView!.viewRect.size.width/2,
                                                    y: mapView!.viewRect.size.height/2))
        
        roadView?.isEnabled = true
        roadView?.linkMapView("mapview")
    
        var markers = [PanoramaMarker]()
        
        markers.append(PanoramaMarker(position: position)) // 해당 position을 표시하는 Marker
        markers.append(PanoramaMarker(pan: 0.7, tilt: 0.1)) // 해당 방향을 표시하는 Marker
    
        roadView?.requestRoadview(position: position, panoID: nil, markers: markers) // 로드뷰 요청시 함께 전달한다.
    }

RoadviewEventDelegate

RoadviewEventDelegate를 구현하여 Roadview에서 발생하는 콜백 이벤트를 받을 수 있습니다. 로드뷰의 Focus변경, 탭 이벤트 뿐만 아니라 요청한 roadview의 성공/실패 여부등도 알 수 있습니다. RoadviewEventDelegate는 대부분 optional로 정의되어 있으므로, adopt하고 원하는 함수를 구현할 수 있습니다.

Minimap


KakaoMap과 Roadview를 동시에 표시하고, Roadview와 KakaoMap을 연결하여 각 뷰의 카메라 이동을 연결할 수 있습니다.

아래 예제는 MapviewInfo와 RoadviewInfo를 이용하여 두 개의 뷰를 생성하여 동시에 표시하고, 로드뷰와 지도를 연동시키는 예제입니다.

// 로드뷰 예제.
class RoadviewSample: APISampleBaseViewController {
    required init?(coder aDecoder: NSCoder) {
        _minimap = false
        super.init(coder: aDecoder)
    }
    
    override func addViews() {
        let defaultPosition: MapPoint = MapPoint(longitude: 126.978365, latitude: 37.566691)
        let mapviewInfo: MapviewInfo = MapviewInfo(viewName: "mapview", viewInfoName: "map", defaultPosition: defaultPosition)
        let roadviewInfo: RoadviewInfo = RoadviewInfo(viewName: "roadview", viewInfoName: "roadview", enabled: true)
        //미니맵을 위한 지도뷰 추가.
        mapController?.addView(mapviewInfo)
        //로드뷰 추가.
        mapController?.addView(roadviewInfo)
    }

    func addViewSucceeded(_ viewName: String, viewInfoName: String) {
        if viewName == "mapview" {
            print("mapview OK")
            let view = mapController?.getView("mapview") as! KakaoMap
            view.viewRect = CGRect(x: 0, y: 0, width: 0, height: 0)
        }
        
        if viewName == "roadview" {
            print("Roadview OK")
            requestRoadview()
        }
    }    
    
    func requestRoadview() {
        let view = mapController?.getView("roadview") as! Roadview
        let defaultPosition: MapPoint = MapPoint(longitude: 126.978365, latitude: 37.566691)
        //좌표로 로드뷰 요청. panoID를 알 경우, panoID를 지정할 수 있다. panoID가 지정되면 해당 panoID로 먼저 검색한 뒤 없으면 좌표로 검색한다.
        view.requestRoadview(position: defaultPosition, panoID: nil)
    }
    
    override func containerDidResized(_ size: CGSize) {
        let mapView: KakaoMap? = mapController?.getView("mapview") as? KakaoMap
        let roadview: Roadview? = mapController?.getView("roadview") as? Roadview
        
        if _minimap {
            roadview?.viewRect = CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height * 0.5)
            mapView?.viewRect = CGRect(x: 0.0, y: size.height * 0.5, width: size.width, height: size.height * 0.5)
        }
        else {
            roadview?.viewRect = CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height)
            mapView?.viewRect = CGRect(x: 0, y: 0, width: 0, height: 0)
        }
    }
    
    @IBAction func minimapButtonClicked(_ sender: Any) {
        _minimap = !_minimap
        
        let mapView: KakaoMap? = mapController?.getView("mapview") as? KakaoMap
        let roadview: Roadview? = mapController?.getView("roadview") as? Roadview
        //로드뷰와 미니맵뷰를 연결한다.
        roadview?.linkMapView("mapview")
        
        //미니맵 on/off 상태에 따라 크기를 조절한다.
        if _minimap {
            roadview?.viewRect = CGRect(x: 0.0, y: 0.0, width: self.view.bounds.size.width, height: self.view.bounds.size.height * 0.65)
            mapView?.viewRect = CGRect(x: 0.0, y: self.view.bounds.size.height * 0.65, width: self.view.bounds.size.width, height: self.view.bounds.size.height * 0.65)
        }
        else {
            roadview?.viewRect = CGRect(x: 0.0, y: 0.0, width: self.view.bounds.size.width, height: self.view.bounds.size.height)
            mapView?.viewRect = CGRect(x: 0, y: 0, width: 0, height: 0)
        }
    }
   
    @IBOutlet weak var minimapButton: UIButton!
    var _minimap: Bool
}