From 8f68ea774cc9d417cc50d6f6842306f162ee7a80 Mon Sep 17 00:00:00 2001 From: Miklos Fazekas Date: Fri, 19 Jun 2020 14:44:03 +0200 Subject: [PATCH] Add padding to MGLMapCamera --- platform/darwin/src/MGLMapCamera.h | 44 ++++++++++++++++++++++++ platform/darwin/src/MGLMapCamera.mm | 53 +++++++++++++++++++++++------ platform/ios/src/MGLMapView.mm | 12 ++++++- 3 files changed, 98 insertions(+), 11 deletions(-) diff --git a/platform/darwin/src/MGLMapCamera.h b/platform/darwin/src/MGLMapCamera.h index c0e40bc33b..a84cb5be7d 100644 --- a/platform/darwin/src/MGLMapCamera.h +++ b/platform/darwin/src/MGLMapCamera.h @@ -4,6 +4,22 @@ #import "MGLFoundation.h" +#if TARGET_OS_IPHONE + #import +#endif + +#if TARGET_OS_IPHONE + #define MGLEdgeInsets UIEdgeInsets + #define MGLEdgeInsetsMake UIEdgeInsetsMake + #define MGLEdgeInsetsEqual UIEdgeInsetsEqualToEdgeInsets + #define MGLEdgeInsetsZero UIEdgeInsetsZero +#else + #define MGLEdgeInsets NSEdgeInsets + #define MGLEdgeInsetsMake NSEdgeInsetsMake + #define MGLEdgeInsetsEqual NSEdgeInsetsEqual + #define MGLEdgeInsetsZero NSEdgeInsetsZero +#endif + NS_ASSUME_NONNULL_BEGIN /** @@ -54,6 +70,11 @@ MGL_EXPORT */ @property (nonatomic) CLLocationDistance viewingDistance; +/** + Padding around the interior of the view that affects the frame of reference for `center`. + */ +@property (nonatomic) MGLEdgeInsets padding; + /** Returns a new camera with all properties set to 0. */ + (instancetype)camera; @@ -118,6 +139,29 @@ MGL_EXPORT pitch:(CGFloat)pitch heading:(CLLocationDirection)heading; +/** + Returns a new camera with the given altitude, pitch, and heading. + + @param centerCoordinate The geographic coordinate on which the map should be + centered. + @param altitude The altitude (measured in meters) above the map at which the + camera should be situated. The altitude may be less than the distance from + the camera’s viewpoint to the camera’s focus point. + @param pitch The viewing angle of the camera, measured in degrees. A value of + `0` results in a camera pointed straight down at the map. Angles greater + than `0` result in a camera angled toward the horizon. + @param heading The camera’s heading, measured in degrees clockwise from true + north. A value of `0` means that the top edge of the map view corresponds to + true north. The value `90` means the top of the map is pointing due east. + The value `180` means the top of the map points due south, and so on. + @param padding Padding around the interior of the view that affects the frame of reference for `center`. + */ ++ (instancetype)cameraLookingAtCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate + altitude:(CLLocationDistance)altitude + pitch:(CGFloat)pitch + heading:(CLLocationDirection)heading + padding:(MGLEdgeInsets)padding; + /** @note This initializer incorrectly interprets the `distance` parameter. To specify the straight-line distance from the viewpoint to `centerCoordinate`, diff --git a/platform/darwin/src/MGLMapCamera.mm b/platform/darwin/src/MGLMapCamera.mm index 0f5dd558a8..447e49ce6a 100644 --- a/platform/darwin/src/MGLMapCamera.mm +++ b/platform/darwin/src/MGLMapCamera.mm @@ -44,7 +44,8 @@ + (instancetype)cameraLookingAtCenterCoordinate:(CLLocationCoordinate2D)centerCo return [[self alloc] initWithCenterCoordinate:centerCoordinate altitude:eyeAltitude pitch:pitch - heading:heading]; + heading:heading + padding:MGLEdgeInsetsZero]; } + (instancetype)cameraLookingAtCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate @@ -60,7 +61,8 @@ + (instancetype)cameraLookingAtCenterCoordinate:(CLLocationCoordinate2D)centerCo return [[self alloc] initWithCenterCoordinate:centerCoordinate altitude:altitude pitch:pitch - heading:heading]; + heading:heading + padding:MGLEdgeInsetsZero]; } + (instancetype)cameraLookingAtCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate @@ -71,7 +73,21 @@ + (instancetype)cameraLookingAtCenterCoordinate:(CLLocationCoordinate2D)centerCo return [[self alloc] initWithCenterCoordinate:centerCoordinate altitude:altitude pitch:pitch - heading:heading]; + heading:heading + padding:MGLEdgeInsetsZero]; +} + ++ (instancetype)cameraLookingAtCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate + altitude:(CLLocationDistance)altitude + pitch:(CGFloat)pitch + heading:(CLLocationDirection)heading + padding:(MGLEdgeInsets)padding +{ + return [[self alloc] initWithCenterCoordinate:centerCoordinate + altitude:altitude + pitch:pitch + heading:heading + padding:padding]; } + (instancetype)cameraLookingAtCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate @@ -91,14 +107,16 @@ - (instancetype)initWithCenterCoordinate:(CLLocationCoordinate2D)centerCoordinat altitude:(CLLocationDistance)altitude pitch:(CGFloat)pitch heading:(CLLocationDirection)heading + padding:(MGLEdgeInsets)padding { - MGLLogDebug(@"Initializing withCenterCoordinate: %@ altitude: %.0fm pitch: %f° heading: %f°", MGLStringFromCLLocationCoordinate2D(centerCoordinate), altitude, pitch, heading); + MGLLogDebug(@"Initializing withCenterCoordinate: %@ altitude: %.0fm pitch: %f° heading: %f° padding:%@ padding; %f, %f, %f, %f", MGLStringFromCLLocationCoordinate2D(centerCoordinate), altitude, pitch, heading, padding.top, padding.left, padding.bottom, padding.right); if (self = [super init]) { _centerCoordinate = centerCoordinate; _altitude = altitude; _pitch = pitch; _heading = heading; + _padding = padding; } return self; } @@ -113,6 +131,10 @@ - (nullable instancetype)initWithCoder:(NSCoder *)coder _altitude = [coder decodeDoubleForKey:@"altitude"]; _pitch = [coder decodeDoubleForKey:@"pitch"]; _heading = [coder decodeDoubleForKey:@"heading"]; + _padding.left = [coder decodeDoubleForKey:@"paddingLeft"]; + _padding.right = [coder decodeDoubleForKey:@"paddingRight"]; + _padding.top = [coder decodeDoubleForKey:@"paddingTop"]; + _padding.bottom = [coder decodeDoubleForKey:@"paddingBottom"]; } return self; } @@ -124,6 +146,10 @@ - (void)encodeWithCoder:(NSCoder *)coder [coder encodeDouble:_altitude forKey:@"altitude"]; [coder encodeDouble:_pitch forKey:@"pitch"]; [coder encodeDouble:_heading forKey:@"heading"]; + [coder encodeDouble:_padding.left forKey:@"paddingLeft"]; + [coder encodeDouble:_padding.right forKey:@"paddingRight"]; + [coder encodeDouble:_padding.top forKey:@"paddingTop"]; + [coder encodeDouble:_padding.bottom forKey:@"paddingBottom"]; } - (id)copyWithZone:(nullable NSZone *)zone @@ -131,7 +157,8 @@ - (id)copyWithZone:(nullable NSZone *)zone return [[[self class] allocWithZone:zone] initWithCenterCoordinate:_centerCoordinate altitude:_altitude pitch:_pitch - heading:_heading]; + heading:_heading + padding:_padding]; } + (NSSet *)keyPathsForValuesAffectingViewingDistance { @@ -151,8 +178,8 @@ - (void)setViewingDistance:(CLLocationDistance)distance { - (NSString *)description { - return [NSString stringWithFormat:@"<%@: %p; centerCoordinate = %f, %f; altitude = %.0fm; heading = %.0f°; pitch = %.0f°>", - NSStringFromClass([self class]), (void *)self, _centerCoordinate.latitude, _centerCoordinate.longitude, _altitude, _heading, _pitch]; + return [NSString stringWithFormat:@"<%@: %p; centerCoordinate = %f, %f; altitude = %.0fm; heading = %.0f°; pitch = %.0f° ; padding = %f, %f, %f, %f>", + NSStringFromClass([self class]), (void *)self, _centerCoordinate.latitude, _centerCoordinate.longitude, _altitude, _heading, _pitch, _padding.top, _padding.left, _padding.bottom, _padding.right]; } - (BOOL)isEqual:(id)other @@ -170,7 +197,8 @@ - (BOOL)isEqual:(id)other return (_centerCoordinate.latitude == otherCamera.centerCoordinate.latitude && _centerCoordinate.longitude == otherCamera.centerCoordinate.longitude && _altitude == otherCamera.altitude - && _pitch == otherCamera.pitch && _heading == otherCamera.heading); + && _pitch == otherCamera.pitch && _heading == otherCamera.heading + && MGLEdgeInsetsEqual(_padding, otherCamera.padding)); } - (BOOL)isEqualToMapCamera:(MGLMapCamera *)otherCamera @@ -184,13 +212,18 @@ - (BOOL)isEqualToMapCamera:(MGLMapCamera *)otherCamera && MGLEqualFloatWithAccuracy(_centerCoordinate.longitude, otherCamera.centerCoordinate.longitude, 1e-6) && MGLEqualFloatWithAccuracy(_altitude, otherCamera.altitude, 1e-6) && MGLEqualFloatWithAccuracy(_pitch, otherCamera.pitch, 1) - && MGLEqualFloatWithAccuracy(_heading, otherCamera.heading, 1)); + && MGLEqualFloatWithAccuracy(_heading, otherCamera.heading, 1)) + && MGLEqualFloatWithAccuracy(_padding.left, otherCamera.padding.left, 1e-6) + && MGLEqualFloatWithAccuracy(_padding.right, otherCamera.padding.right, 1e-6) + && MGLEqualFloatWithAccuracy(_padding.top, otherCamera.padding.top, 1e-6) + && MGLEqualFloatWithAccuracy(_padding.bottom, otherCamera.padding.bottom, 1e-6); } - (NSUInteger)hash { return (@(_centerCoordinate.latitude).hash + @(_centerCoordinate.longitude).hash - + @(_altitude).hash + @(_pitch).hash + @(_heading).hash); + + @(_altitude).hash + @(_pitch).hash + @(_heading).hash + @(_padding.left).hash + + @(_padding.right).hash + @(_padding.top).hash + @(_padding.bottom).hash); } @end diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 793264027e..314b950d29 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -4021,7 +4021,14 @@ - (MGLMapCamera *)cameraForCameraOptions:(const mbgl::CameraOptions &)cameraOpti CLLocationDirection direction = cameraOptions.bearing ? mbgl::util::wrap(*cameraOptions.bearing, 0., 360.) : self.direction; CGFloat pitch = cameraOptions.pitch ? *cameraOptions.pitch : *mapCamera.pitch; CLLocationDistance altitude = MGLAltitudeForZoomLevel(zoomLevel, pitch, centerCoordinate.latitude, self.frame.size); - return [MGLMapCamera cameraLookingAtCenterCoordinate:centerCoordinate altitude:altitude pitch:pitch heading:direction]; + MGLEdgeInsets padding = MGLEdgeInsetsZero; + if (cameraOptions.padding) { + padding = MGLEdgeInsetsMake(cameraOptions.padding->top(), + cameraOptions.padding->left(), + cameraOptions.padding->bottom(), + cameraOptions.padding->right()); + } + return [MGLMapCamera cameraLookingAtCenterCoordinate:centerCoordinate altitude:altitude pitch:pitch heading:direction padding:padding]; } /// Returns a CameraOptions object that specifies parameters for animating to @@ -4045,6 +4052,9 @@ - (MGLMapCamera *)cameraForCameraOptions:(const mbgl::CameraOptions &)cameraOpti { options.pitch = camera.pitch; } + if (! MGLEdgeInsetsEqual(camera.padding, MGLEdgeInsetsZero)) { + options.padding = MGLEdgeInsetsFromNSEdgeInsets(camera.padding); + } return options; }