Skip to content

Commit 86b632c

Browse files
authored
Add animate to bounds on Map from LatLngBounds (#22)
* add setBounds based on setVisibleMapRect from Map * add newLatLngBounds to create CameraUpdate * add parsed from Swift * add function to example * add convert coordinate to point * add example * remove printing
1 parent ab2f409 commit 86b632c

File tree

8 files changed

+136
-2
lines changed

8 files changed

+136
-2
lines changed

example/lib/animate_camera.dart

+13
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,19 @@ class AnimateCameraState extends State<AnimateCamera> {
8989
},
9090
child: const Text('newLatLngZoom'),
9191
),
92+
FlatButton(
93+
onPressed: () {
94+
mapController.animateCamera(
95+
CameraUpdate.newLatLngBounds(
96+
LatLngBounds(
97+
southwest: LatLng(37.749146, -122.71829295684518),
98+
northeast: LatLng(37.94134713198227, -122.498971)
99+
),
100+
11.0,
101+
),
102+
);
103+
},
104+
child: const Text('newLatLngBounds'))
92105
],
93106
),
94107
Column(

example/lib/move_camera.dart

+14
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,20 @@ class MoveCameraState extends State<MoveCamera> {
8888
},
8989
child: const Text('newLatLngZoom'),
9090
),
91+
FlatButton(
92+
onPressed: () {
93+
mapController.moveCamera(
94+
CameraUpdate.newLatLngBounds(
95+
LatLngBounds(
96+
southwest: LatLng(37.749146, -122.71829295684518),
97+
northeast: LatLng(37.94134713198227, -122.498971)
98+
),
99+
11.0,
100+
),
101+
);
102+
},
103+
child: const Text('newLatLngBounds'),
104+
),
91105
],
92106
),
93107
Column(

example/lib/place_annotation.dart

+12
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,18 @@ class PlaceAnnotationBodyState extends State<PlaceAnnotationBody> {
254254
child: const Text('add defaultAnnotation'),
255255
onPressed: () => _add('pin'),
256256
),
257+
FlatButton(
258+
child: const Text('Get Visible Region Bounds'),
259+
onPressed: () async {
260+
final point = await controller.getScreenCoordinate(LatLng(
261+
center.latitude +
262+
sin(_annotationIdCounter * pi / 6.0) / 20.0,
263+
center.longitude +
264+
cos(_annotationIdCounter * pi / 6.0) /
265+
20.0));
266+
print("Point $point");
267+
},
268+
),
257269
FlatButton(
258270
child: const Text('add markerAnnotation'),
259271
onPressed: () => _add('marker'),

ios/Classes/MapView/AppleMapController.swift

+22-2
Original file line numberDiff line numberDiff line change
@@ -199,15 +199,30 @@ public class AppleMapController : NSObject, FlutterPlatformView, MKMapViewDelega
199199
case "camera#animate":
200200
let positionData :Dictionary<String, Any> = self.toPositionData(data: args["cameraUpdate"] as! Array<Any>, animated: true)
201201
if !positionData.isEmpty {
202-
self.mapView.setCenterCoordinate(positionData, animated: true)
202+
guard let _ = positionData["moveToBounds"] else {
203+
self.mapView.setCenterCoordinate(positionData, animated: true)
204+
return
205+
}
206+
self.mapView.setBounds(positionData, animated: true)
203207
}
204208
result(nil)
205209
case "camera#move":
206210
let positionData :Dictionary<String, Any> = self.toPositionData(data: args["cameraUpdate"] as! Array<Any>, animated: false)
207211
if !positionData.isEmpty {
208-
self.mapView.setCenterCoordinate(positionData, animated: false)
212+
guard let _ = positionData["moveToBounds"] else {
213+
self.mapView.setCenterCoordinate(positionData, animated: false)
214+
return
215+
}
216+
self.mapView.setBounds(positionData, animated: false)
209217
}
210218
result(nil)
219+
case "camera#convert":
220+
guard let annotation = args["annotation"] as? Array<Double> else {
221+
result(nil)
222+
return
223+
}
224+
let point = self.mapView.convert(CLLocationCoordinate2D(latitude: annotation[0] , longitude: annotation[1]), toPointTo: self.view())
225+
result(["point": [point.x, point.y]])
211226
default:
212227
result(FlutterMethodNotImplemented)
213228
return
@@ -261,6 +276,11 @@ public class AppleMapController : NSObject, FlutterPlatformView, MKMapViewDelega
261276
let zoom: Double = data[2] as? Double ?? 0
262277
positionData = ["target": _positionData, "zoom": zoom]
263278
}
279+
case "newLatLngBounds":
280+
if let _positionData: Array<Any> = data[1] as? Array<Any> {
281+
let padding: Double = data[2] as? Double ?? 0
282+
positionData = ["target": _positionData, "padding": padding, "moveToBounds": true]
283+
}
264284
case "zoomBy":
265285
if let zoomBy: Double = data[1] as? Double {
266286
mapView.zoomBy(zoomBy: zoomBy, animated: animated)

ios/Classes/MapView/MapViewExtension.swift

+41
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,16 @@ public extension MKMapView {
136136
}
137137
}
138138

139+
func setBounds(_ positionData: Dictionary<String, Any>, animated: Bool) {
140+
guard let targetList :Array<Array<CLLocationDegrees>> = positionData["target"] as? Array<Array<CLLocationDegrees>> else { return }
141+
let padding :Double = positionData["padding"] as? Double ?? 0
142+
let coodinates: Array<CLLocationCoordinate2D> = targetList.map { (coordinate : Array<CLLocationDegrees>) in
143+
return CLLocationCoordinate2D(latitude: coordinate[0], longitude: coordinate[1])
144+
}
145+
guard let mapRect = coodinates.mapRect() else { return }
146+
self.setVisibleMapRect(mapRect, edgePadding: UIEdgeInsets(top: CGFloat(padding), left: CGFloat(padding), bottom: CGFloat(padding), right: CGFloat(padding)), animated: animated)
147+
}
148+
139149
func setCenterCoordinateRegion(centerCoordinate: CLLocationCoordinate2D, zoomLevel: Double, animated: Bool) {
140150
// clamp large numbers to 28
141151
let zoomL = min(zoomLevel, 28);
@@ -315,3 +325,34 @@ public extension MKMapView {
315325
Holder._heading = newHeading
316326
}
317327
}
328+
329+
extension Array where Element == CLLocationCoordinate2D {
330+
func mapRect() -> MKMapRect? {
331+
return map(MKMapPoint.init).mapRect()
332+
}
333+
}
334+
335+
extension Array where Element == CLLocation {
336+
func mapRect() -> MKMapRect? {
337+
return map { MKMapPoint($0.coordinate) }.mapRect()
338+
}
339+
}
340+
341+
extension Array where Element == MKMapPoint {
342+
func mapRect() -> MKMapRect? {
343+
guard count > 0 else { return nil }
344+
345+
let xs = map { $0.x }
346+
let ys = map { $0.y }
347+
348+
let west = xs.min()!
349+
let east = xs.max()!
350+
let width = east - west
351+
352+
let south = ys.min()!
353+
let north = ys.max()!
354+
let height = north - south
355+
356+
return MKMapRect(x: west, y: south, width: width, height: height)
357+
}
358+
}

lib/src/camera.dart

+12
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,18 @@ class CameraUpdate {
109109
);
110110
}
111111

112+
/// Returns a camera update that transforms the camera so that the specified
113+
/// geographical bounding box is centered in the map view at the greatest
114+
/// possible zoom level. A non-zero [padding] insets the bounding box from the
115+
/// map view's edges. The camera's new tilt and bearing will both be 0.0.
116+
static CameraUpdate newLatLngBounds(LatLngBounds bounds, double padding) {
117+
return CameraUpdate._(<dynamic>[
118+
'newLatLngBounds',
119+
bounds._toJson(),
120+
padding,
121+
]);
122+
}
123+
112124
/// Returns a camera update that modifies the camera zoom level by the
113125
/// specified amount. The optional [focus] is a screen point whose underlying
114126
/// geographical location should be invariant, if possible, by the movement.

lib/src/controller.dart

+17
Original file line numberDiff line numberDiff line change
@@ -233,4 +233,21 @@ class AppleMapController {
233233

234234
return LatLngBounds(northeast: northeast, southwest: southwest);
235235
}
236+
237+
238+
/// A projection is used to translate between on screen location and geographic coordinates.
239+
/// Screen location is in screen pixels (not display pixels) with respect to the top left corner
240+
/// of the map, not necessarily of the whole screen.
241+
Future<Offset> getScreenCoordinate(LatLng latLng) async {
242+
final point = await channel
243+
.invokeMapMethod<String, dynamic>(
244+
'camera#convert', <String, dynamic>{
245+
'annotation': [latLng.latitude, latLng.longitude]
246+
});
247+
if (!point.containsKey('point')) {
248+
return null;
249+
}
250+
final doubles = List<double>.from(point['point']);
251+
return Offset(doubles.first, doubles.last);
252+
}
236253
}

lib/src/location.dart

+5
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ class LatLngBounds {
114114
o.northeast == northeast;
115115
}
116116

117+
/// Converts this object to something serializable in JSON.
118+
dynamic _toJson() {
119+
return <dynamic>[southwest._toJson(), northeast._toJson()];
120+
}
121+
117122
@override
118123
int get hashCode => hashValues(southwest, northeast);
119124
}

0 commit comments

Comments
 (0)