react-native-maps 2.0.0-beta.11 → 2.0.0-beta.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -434,26 +434,34 @@ public class MapViewModule extends ReactContextBaseJavaModule {
434
434
  promise.reject("RNMMapView.map is not valid");
435
435
  return;
436
436
  }
437
- LatLngBounds.Builder builder = new LatLngBounds.Builder();
438
-
439
437
  boolean addedPosition = false;
440
438
 
439
+ double maxLatitude = -Double.MAX_VALUE;
440
+ double minLatitude = Double.MAX_VALUE;
441
+ double maxLongitude = -Double.MAX_VALUE;
442
+ double minLongitude = Double.MAX_VALUE;
443
+
441
444
  for (MapFeature feature : view.features) {
442
445
  if (feature instanceof MapMarker) {
443
- Marker marker = (Marker) feature.getFeature();
444
- builder.include(marker.getPosition());
446
+ LatLng position = ((Marker) feature.getFeature()).getPosition();
447
+ maxLatitude = Math.max(maxLatitude, position.latitude);
448
+ minLatitude = Math.min(minLatitude, position.latitude);
449
+ maxLongitude = Math.max(maxLongitude, position.longitude);
450
+ minLongitude = Math.min(minLongitude, position.longitude);
445
451
  addedPosition = true;
446
452
  }
447
453
  // TODO(lmr): may want to include shapes / etc.
448
454
  }
449
- if (addedPosition) {
450
- LatLngBounds bounds = builder.build();
451
- CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, view.baseMapPadding);
452
-
453
- if (edgePadding != null) {
454
- view.map.setPadding(edgePadding.getInt("left"), edgePadding.getInt("top"),
455
- edgePadding.getInt("right"), edgePadding.getInt("bottom"));
456
- }
455
+ if(!addedPosition) {
456
+ // nothing to do
457
+ promise.resolve(null);
458
+ } else {
459
+ Map<String, Double> paddedBoundary = padBoundary(view, maxLatitude, minLatitude, maxLongitude, minLongitude, edgePadding);
460
+ LatLngBounds bounds = new LatLngBounds(
461
+ new LatLng(paddedBoundary.get("minLatitude"), paddedBoundary.get("minLongitude")), // southwest
462
+ new LatLng(paddedBoundary.get("maxLatitude"), paddedBoundary.get("maxLongitude")) // northeast
463
+ );
464
+ CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 0);
457
465
 
458
466
  if (duration > 0) {
459
467
  view.map.animateCamera(cu, duration, new GoogleMap.CancelableCallback() {
@@ -491,7 +499,6 @@ public class MapViewModule extends ReactContextBaseJavaModule {
491
499
  promise.reject("RNMMapView.map is not valid");
492
500
  return;
493
501
  }
494
- LatLngBounds.Builder builder = new LatLngBounds.Builder();
495
502
 
496
503
  String[] markerIDs = new String[markersIds.size()];
497
504
  for (int i = 0; i < markersIds.size(); i++) {
@@ -502,25 +509,35 @@ public class MapViewModule extends ReactContextBaseJavaModule {
502
509
 
503
510
  List<String> markerIDList = Arrays.asList(markerIDs);
504
511
 
512
+ double maxLatitude = -Double.MAX_VALUE;
513
+ double minLatitude = Double.MAX_VALUE;
514
+ double maxLongitude = -Double.MAX_VALUE;
515
+ double minLongitude = Double.MAX_VALUE;
516
+
505
517
  for (MapFeature feature : view.features) {
506
518
  if (feature instanceof MapMarker) {
507
519
  String identifier = ((MapMarker) feature).getIdentifier();
508
- Marker marker = (Marker) feature.getFeature();
509
520
  if (markerIDList.contains(identifier)) {
510
- builder.include(marker.getPosition());
521
+ LatLng position = ((Marker) feature.getFeature()).getPosition();
522
+ maxLatitude = Math.max(maxLatitude, position.latitude);
523
+ minLatitude = Math.min(minLatitude, position.latitude);
524
+ maxLongitude = Math.max(maxLongitude, position.longitude);
525
+ minLongitude = Math.min(minLongitude, position.longitude);
511
526
  addedPosition = true;
512
527
  }
513
528
  }
514
529
  }
515
530
 
516
- if (addedPosition) {
517
- LatLngBounds bounds = builder.build();
518
- CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, view.baseMapPadding);
519
-
520
- if (edgePadding != null) {
521
- view.map.setPadding(edgePadding.getInt("left"), edgePadding.getInt("top"),
522
- edgePadding.getInt("right"), edgePadding.getInt("bottom"));
523
- }
531
+ if(!addedPosition) {
532
+ // nothing to do
533
+ promise.resolve(null);
534
+ } else {
535
+ Map<String, Double> paddedBoundary = padBoundary(view, maxLatitude, minLatitude, maxLongitude, minLongitude, edgePadding);
536
+ LatLngBounds bounds = new LatLngBounds(
537
+ new LatLng(paddedBoundary.get("minLatitude"), paddedBoundary.get("minLongitude")), // southwest
538
+ new LatLng(paddedBoundary.get("maxLatitude"), paddedBoundary.get("maxLongitude")) // northeast
539
+ );
540
+ CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 0);
524
541
 
525
542
  if (duration > 0) {
526
543
  view.map.animateCamera(cu, duration, new GoogleMap.CancelableCallback() {
@@ -558,21 +575,28 @@ public class MapViewModule extends ReactContextBaseJavaModule {
558
575
  return;
559
576
  }
560
577
 
561
- LatLngBounds.Builder builder = new LatLngBounds.Builder();
578
+ double maxLatitude = -Double.MAX_VALUE;
579
+ double minLatitude = Double.MAX_VALUE;
580
+ double maxLongitude = -Double.MAX_VALUE;
581
+ double minLongitude = Double.MAX_VALUE;
562
582
 
563
583
  for (int i = 0; i < coordinates.size(); i++) {
564
584
  ReadableMap latLng = coordinates.getMap(i);
565
585
  double lat = latLng.getDouble("latitude");
566
586
  double lng = latLng.getDouble("longitude");
567
- builder.include(new LatLng(lat, lng));
587
+ maxLatitude = Math.max(maxLatitude, lat);
588
+ minLatitude = Math.min(minLatitude, lat);
589
+ maxLongitude = Math.max(maxLongitude, lng);
590
+ minLongitude = Math.min(minLongitude, lng);
568
591
  }
569
592
 
570
- LatLngBounds bounds = builder.build();
571
- CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, view.baseMapPadding);
593
+ Map<String, Double> paddedBoundary = padBoundary(view, maxLatitude, minLatitude, maxLongitude, minLongitude, edgePadding);
594
+ LatLngBounds bounds = new LatLngBounds(
595
+ new LatLng(paddedBoundary.get("minLatitude"), paddedBoundary.get("minLongitude")), // southwest
596
+ new LatLng(paddedBoundary.get("maxLatitude"), paddedBoundary.get("maxLongitude")) // northeast
597
+ );
572
598
 
573
- if (edgePadding != null) {
574
- view.appendMapPadding(edgePadding.getInt("left"), edgePadding.getInt("top"), edgePadding.getInt("right"), edgePadding.getInt("bottom"));
575
- }
599
+ CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 0);
576
600
 
577
601
  if (duration > 0) {
578
602
  view.map.animateCamera(cu, duration, new GoogleMap.CancelableCallback() {
@@ -590,9 +614,29 @@ public class MapViewModule extends ReactContextBaseJavaModule {
590
614
  view.map.moveCamera(cu);
591
615
  promise.resolve(null);
592
616
  }
593
- // Move the google logo to the default base padding value.
594
- view.map.setPadding(view.baseLeftMapPadding, view.baseTopMapPadding, view.baseRightMapPadding, view.baseBottomMapPadding);
595
617
  }
596
618
  });
597
619
  }
620
+
621
+ private Map<String, Double> padBoundary(MapView mapView, double maxLat, double minLat, double maxLng, double minLng, ReadableMap edgePadding) {
622
+ double latitudeDelta = maxLat - minLat;
623
+ double longitudeDelta = maxLng - minLng;
624
+ float displayDensity = context.getResources().getDisplayMetrics().density;
625
+ double mapViewHeight = mapView.getHeight() / displayDensity;
626
+ double mapViewWidth = mapView.getWidth() / displayDensity;
627
+ double latPerHeight = latitudeDelta / mapViewHeight;
628
+ double lngPerWidth = longitudeDelta / mapViewWidth;
629
+ double paddedMaxLatitude = maxLat + latPerHeight * edgePadding.getInt("top");
630
+ double paddedMinLatitude = minLat - latPerHeight * edgePadding.getInt("bottom");
631
+ double paddedMaxLongitude = maxLng + lngPerWidth * edgePadding.getInt("right");
632
+ double paddedMinLongitude = minLng - lngPerWidth * edgePadding.getInt("left");
633
+
634
+ Map<String,Double> paddedBoundary = new HashMap<String,Double>();
635
+ paddedBoundary.put("maxLatitude", paddedMaxLatitude);
636
+ paddedBoundary.put("minLatitude", paddedMinLatitude);
637
+ paddedBoundary.put("maxLongitude", paddedMaxLongitude);
638
+ paddedBoundary.put("minLongitude", paddedMinLongitude);
639
+
640
+ return paddedBoundary;
641
+ }
598
642
  }
@@ -261,17 +261,13 @@ RCT_EXPORT_METHOD(fitToElements:(nonnull NSNumber *)reactTag
261
261
 
262
262
  GMSCameraUpdate* cameraUpdate;
263
263
 
264
- if ([edgePadding count] != 0) {
265
- // Set Map viewport
266
- CGFloat top = [RCTConvert CGFloat:edgePadding[@"top"]];
267
- CGFloat right = [RCTConvert CGFloat:edgePadding[@"right"]];
268
- CGFloat bottom = [RCTConvert CGFloat:edgePadding[@"bottom"]];
269
- CGFloat left = [RCTConvert CGFloat:edgePadding[@"left"]];
264
+ // Set Map viewport
265
+ CGFloat top = [RCTConvert CGFloat:edgePadding[@"top"]];
266
+ CGFloat right = [RCTConvert CGFloat:edgePadding[@"right"]];
267
+ CGFloat bottom = [RCTConvert CGFloat:edgePadding[@"bottom"]];
268
+ CGFloat left = [RCTConvert CGFloat:edgePadding[@"left"]];
270
269
 
271
- cameraUpdate = [GMSCameraUpdate fitBounds:bounds withEdgeInsets:UIEdgeInsetsMake(top, left, bottom, right)];
272
- } else {
273
- cameraUpdate = [GMSCameraUpdate fitBounds:bounds withPadding:55.0f];
274
- }
270
+ cameraUpdate = [GMSCameraUpdate fitBounds:bounds withEdgeInsets:UIEdgeInsetsMake(top, left, bottom, right)];
275
271
  if (duration > 0.0f) {
276
272
  [CATransaction begin];
277
273
  [CATransaction setCompletionBlock:^{
@@ -287,21 +287,62 @@ RCT_EXPORT_METHOD(fitToElements:(nonnull NSNumber *)reactTag
287
287
  RCTLogError(@"Invalid view returned from registry, expecting RNMMap, got: %@", view);
288
288
  } else {
289
289
  RNMMap *mapView = (RNMMap *)view;
290
+
291
+ if(mapView.annotations.count < 1) {
292
+ resolve(nil);
293
+ } else {
294
+ CLLocationDegrees minLatitude = DBL_MAX;
295
+ CLLocationDegrees maxLatitude = -DBL_MAX;
296
+ CLLocationDegrees minLongitude = DBL_MAX;
297
+ CLLocationDegrees maxLongitude = -DBL_MAX;
298
+
299
+ for(id<MKAnnotation> annotation in mapView.annotations) {
300
+ double annotationLat = annotation.coordinate.latitude;
301
+ double annotationLong = annotation.coordinate.longitude;
302
+ minLatitude = fmin(annotationLat, minLatitude);
303
+ maxLatitude = fmax(annotationLat, maxLatitude);
304
+ minLongitude = fmin(annotationLong, minLongitude);
305
+ maxLongitude = fmax(annotationLong, maxLongitude);
306
+ }
307
+
308
+ double latitudeDelta = maxLatitude - minLatitude;
309
+ double longitudeDelta = maxLongitude - minLongitude;
310
+
311
+ double mapViewHeight = mapView.bounds.size.height;
312
+ double mapViewWidth = mapView.bounds.size.width;
313
+
314
+ double latPerHeight = latitudeDelta / mapViewHeight;
315
+ double lngPerWidth = longitudeDelta / mapViewWidth;
316
+
317
+ CGFloat topPadding = [RCTConvert CGFloat:edgePadding[@"top"]];
318
+ CGFloat rightPadding = [RCTConvert CGFloat:edgePadding[@"right"]];
319
+ CGFloat bottomPadding = [RCTConvert CGFloat:edgePadding[@"bottom"]];
320
+ CGFloat leftPadding = [RCTConvert CGFloat:edgePadding[@"left"]];
321
+
322
+ maxLatitude = maxLatitude + topPadding * latPerHeight;
323
+ minLatitude = minLatitude - bottomPadding * latPerHeight;
324
+ maxLongitude = maxLongitude + rightPadding * lngPerWidth;
325
+ minLongitude = minLongitude - leftPadding * lngPerWidth;
326
+
327
+ MKCoordinateRegion region;
328
+ region.center.latitude = (minLatitude + maxLatitude) / 2;
329
+ region.center.longitude = (minLongitude + maxLongitude) / 2;
330
+ // if fitting a single marker or if all markers are aligned, the delta will be zero (infinite zoom)
331
+ // this will cause mapkit not to zoom at all. Picking an arbitrary small number to circumvent
332
+ region.span.latitudeDelta = fmax(maxLatitude - minLatitude, 0.000001);
333
+ region.span.longitudeDelta = fmax(maxLongitude - minLongitude, 0.000001);
290
334
 
291
- // TODO(lmr): we potentially want to include overlays here... and could concat the two arrays together.
292
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
293
335
  if(duration > 0.0f) {
294
336
  [RNMMap animateWithDuration:duration/1000 animations:^{
295
- [mapView showAnnotations:mapView.annotations animated:YES];
337
+ [mapView setRegion:region animated:YES];
296
338
  } completion:^(BOOL finished){
297
339
  resolve(nil);
298
340
  }];
299
341
  } else {
300
- [mapView showAnnotations:mapView.annotations animated:NO];
342
+ [mapView setRegion:region animated:NO];
301
343
  resolve(nil);
302
344
  }
303
-
304
- });
345
+ }
305
346
  }
306
347
  }];
307
348
  }
@@ -328,17 +369,62 @@ RCT_EXPORT_METHOD(fitToSuppliedMarkers:(nonnull NSNumber *)reactTag
328
369
  }];
329
370
 
330
371
  NSArray *filteredMarkers = [mapView.annotations filteredArrayUsingPredicate:filterMarkers];
372
+
373
+ if(filteredMarkers.count < 1) {
374
+ resolve(nil);
375
+ } else {
376
+ CLLocationDegrees minLatitude = DBL_MAX;
377
+ CLLocationDegrees maxLatitude = -DBL_MAX;
378
+ CLLocationDegrees minLongitude = DBL_MAX;
379
+ CLLocationDegrees maxLongitude = -DBL_MAX;
380
+
381
+ for(id<MKAnnotation> annotation in filteredMarkers) {
382
+ double annotationLat = annotation.coordinate.latitude;
383
+ double annotationLong = annotation.coordinate.longitude;
384
+ minLatitude = fmin(annotationLat, minLatitude);
385
+ maxLatitude = fmax(annotationLat, maxLatitude);
386
+ minLongitude = fmin(annotationLong, minLongitude);
387
+ maxLongitude = fmax(annotationLong, maxLongitude);
388
+ }
389
+
390
+ double latitudeDelta = maxLatitude - minLatitude;
391
+ double longitudeDelta = maxLongitude - minLongitude;
392
+
393
+ double mapViewHeight = mapView.bounds.size.height;
394
+ double mapViewWidth = mapView.bounds.size.width;
395
+
396
+ double latPerHeight = latitudeDelta / mapViewHeight;
397
+ double lngPerWidth = longitudeDelta / mapViewWidth;
398
+
399
+ CGFloat topPadding = [RCTConvert CGFloat:edgePadding[@"top"]];
400
+ CGFloat rightPadding = [RCTConvert CGFloat:edgePadding[@"right"]];
401
+ CGFloat bottomPadding = [RCTConvert CGFloat:edgePadding[@"bottom"]];
402
+ CGFloat leftPadding = [RCTConvert CGFloat:edgePadding[@"left"]];
403
+
404
+ maxLatitude = maxLatitude + topPadding * latPerHeight;
405
+ minLatitude = minLatitude - bottomPadding * latPerHeight;
406
+ maxLongitude = maxLongitude + rightPadding * lngPerWidth;
407
+ minLongitude = minLongitude - leftPadding * lngPerWidth;
408
+
409
+ MKCoordinateRegion region;
410
+ region.center.latitude = (minLatitude + maxLatitude) / 2;
411
+ region.center.longitude = (minLongitude + maxLongitude) / 2;
412
+ // if fitting a single marker or if all markers are aligned, the delta will be zero (infinite zoom)
413
+ // this will cause mapkit not to zoom at all. Picking an arbitrary small number to circumvent
414
+ region.span.latitudeDelta = fmax(maxLatitude - minLatitude, 0.000001);
415
+ region.span.longitudeDelta = fmax(maxLongitude - minLongitude, 0.000001);
331
416
 
332
- if(duration > 0.0f) {
333
- [RNMMap animateWithDuration:duration/1000 animations:^{
334
- [mapView showAnnotations:filteredMarkers animated:YES];
335
- } completion:^(BOOL finished){
336
- resolve(nil);
337
- }];
417
+ if(duration > 0.0f) {
418
+ [RNMMap animateWithDuration:duration/1000 animations:^{
419
+ [mapView setRegion:region animated:YES];
420
+ } completion:^(BOOL finished){
421
+ resolve(nil);
422
+ }];
338
423
  } else {
339
- [mapView showAnnotations:filteredMarkers animated:NO];
424
+ [mapView setRegion:region animated:NO];
340
425
  resolve(nil);
341
426
  }
427
+ }
342
428
  }
343
429
  }];
344
430
  }
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "main": "lib/index.js",
6
6
  "author": "Leland Richardson <leland.m.richardson@gmail.com>",
7
7
  "homepage": "https://github.com/react-native-maps/react-native-maps#readme",
8
- "version": "2.0.0-beta.11",
8
+ "version": "2.0.0-beta.12",
9
9
  "license": "MIT",
10
10
  "scripts": {
11
11
  "lint": "eslint . --max-warnings 0",