diff --git a/README.md b/README.md index b8e459f52..ed136f9be 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,10 @@ This project uses Mapbox vector tiles, which requires a Mapbox account and a Map After you get the key, place it in project's Android directory: - Add your access token to `$project_dir/example/android/app/src/values/developer-config.xml` -##### iOS -Add this lines to your Info.plist + +#### iOS +Add these lines to your Info.plist + ```plist io.flutter.embedded_views_preview diff --git a/ios/Classes/Convert.swift b/ios/Classes/Convert.swift index 858191ff9..9e08775db 100644 --- a/ios/Classes/Convert.swift +++ b/ios/Classes/Convert.swift @@ -34,4 +34,90 @@ class Convert { delegate.setMyLocationEnabled(myLocationEnabled: myLocationEnabled) } } + + class func parseCameraUpdate(cameraUpdate: [Any], mapView: MGLMapView) -> MGLMapCamera? { + guard let type = cameraUpdate[0] as? String else { return nil } + switch (type) { + case "newCameraPosition": + guard let cameraPosition = cameraUpdate[1] as? [String: Any] else { return nil } + return MGLMapCamera.fromDict(cameraPosition, mapView: mapView) + case "newLatLng": + guard let coordinate = cameraUpdate[1] as? [Double] else { return nil } + let camera = mapView.camera + camera.centerCoordinate = CLLocationCoordinate2D.fromArray(coordinate) + return camera + case "newLatLngBounds": + guard let bounds = cameraUpdate[1] as? [[Double]] else { return nil } + guard let padding = cameraUpdate[2] as? CGFloat else { return nil } + return mapView.cameraThatFitsCoordinateBounds(MGLCoordinateBounds.fromArray(bounds), edgePadding: UIEdgeInsets.init(top: padding, left: padding, bottom: padding, right: padding)) + case "newLatLngZoom": + guard let coordinate = cameraUpdate[1] as? [Double] else { return nil } + guard let zoom = cameraUpdate[2] as? Double else { return nil } + let camera = mapView.camera + camera.centerCoordinate = CLLocationCoordinate2D.fromArray(coordinate) + let altitude = getAltitude(zoom: zoom, mapView: mapView) + return MGLMapCamera(lookingAtCenter: camera.centerCoordinate, altitude: altitude, pitch: camera.pitch, heading: camera.heading) + case "scrollBy": + guard let x = cameraUpdate[1] as? CGFloat else { return nil } + guard let y = cameraUpdate[2] as? CGFloat else { return nil } + let camera = mapView.camera + let mapPoint = mapView.convert(camera.centerCoordinate, toPointTo: mapView) + let movedPoint = CGPoint(x: mapPoint.x + x, y: mapPoint.y + y) + camera.centerCoordinate = mapView.convert(movedPoint, toCoordinateFrom: mapView) + return camera + case "zoomBy": + guard let zoomBy = cameraUpdate[1] as? Double else { return nil } + let camera = mapView.camera + let zoom = getZoom(mapView: mapView) + let altitude = getAltitude(zoom: zoom+zoomBy, mapView: mapView) + camera.altitude = altitude + if (cameraUpdate.count == 2) { + return camera + } else { + guard let point = cameraUpdate[2] as? [CGFloat], point.count == 2 else { return nil } + let movedPoint = CGPoint(x: point[0], y: point[1]) + camera.centerCoordinate = mapView.convert(movedPoint, toCoordinateFrom: mapView) + return camera + } + case "zoomIn": + let camera = mapView.camera + let zoom = getZoom(mapView: mapView) + let altitude = getAltitude(zoom: zoom + 1, mapView: mapView) + camera.altitude = altitude + return camera + case "zoomOut": + let camera = mapView.camera + let zoom = getZoom(mapView: mapView) + let altitude = getAltitude(zoom: zoom - 1, mapView: mapView) + camera.altitude = altitude + return camera + case "zoomTo": + guard let zoom = cameraUpdate[1] as? Double else { return nil } + let camera = mapView.camera + let altitude = getAltitude(zoom: zoom, mapView: mapView) + camera.altitude = altitude + return camera + case "bearingTo": + guard let bearing = cameraUpdate[1] as? Double else { return nil } + let camera = mapView.camera + camera.heading = bearing + return camera + case "tiltTo": + guard let tilt = cameraUpdate[1] as? CGFloat else { return nil } + let camera = mapView.camera + camera.pitch = tilt + return camera + default: + print("\(type) not implemented!") + } + return nil + } + + class func getZoom(mapView: MGLMapView) -> Double { + return MGLZoomLevelForAltitude(mapView.camera.altitude, mapView.camera.pitch, mapView.camera.centerCoordinate.latitude, mapView.frame.size) + } + + class func getAltitude(zoom: Double, mapView: MGLMapView) -> Double { + return MGLAltitudeForZoomLevel(zoom, mapView.camera.pitch, mapView.camera.centerCoordinate.latitude, mapView.frame.size) + } } diff --git a/ios/Classes/MapboxMapController.swift b/ios/Classes/MapboxMapController.swift index ac2507484..2ba4b0a4e 100644 --- a/ios/Classes/MapboxMapController.swift +++ b/ios/Classes/MapboxMapController.swift @@ -55,6 +55,18 @@ class MapboxMapController: NSObject, FlutterPlatformView, MGLMapViewDelegate, Ma } else { result(nil) } + case "camera#move": + guard let arguments = methodCall.arguments as? [String: Any] else { return } + guard let cameraUpdate = arguments["cameraUpdate"] as? [Any] else { return } + if let camera = Convert.parseCameraUpdate(cameraUpdate: cameraUpdate, mapView: mapView) { + mapView.setCamera(camera, animated: false) + } + case "camera#animate": + guard let arguments = methodCall.arguments as? [String: Any] else { return } + guard let cameraUpdate = arguments["cameraUpdate"] as? [Any] else { return } + if let camera = Convert.parseCameraUpdate(cameraUpdate: cameraUpdate, mapView: mapView) { + mapView.setCamera(camera, animated: true) + } default: result(FlutterMethodNotImplemented) }