diff options
Diffstat (limited to 'platform/ios/src')
-rw-r--r-- | platform/ios/src/MGLFaux3DUserLocationAnnotationView.m | 7 | ||||
-rw-r--r-- | platform/ios/src/MGLMapView.h | 17 | ||||
-rw-r--r-- | platform/ios/src/MGLMapView.mm | 109 |
3 files changed, 83 insertions, 50 deletions
diff --git a/platform/ios/src/MGLFaux3DUserLocationAnnotationView.m b/platform/ios/src/MGLFaux3DUserLocationAnnotationView.m index 6db9c0db10..5f67f24f4e 100644 --- a/platform/ios/src/MGLFaux3DUserLocationAnnotationView.m +++ b/platform/ios/src/MGLFaux3DUserLocationAnnotationView.m @@ -460,11 +460,8 @@ const CGFloat MGLUserLocationAnnotationArrowSize = MGLUserLocationAnnotationPuck - (CGFloat)calculateAccuracyRingSize { - CGFloat latitudeRadians = MGLRadiansFromDegrees(self.userLocation.coordinate.latitude); - CGFloat metersPerPoint = [self.mapView metersPerPointAtLatitude:self.userLocation.coordinate.latitude]; - CGFloat pixelRadius = self.userLocation.location.horizontalAccuracy / cos(latitudeRadians) / metersPerPoint; - - return pixelRadius * 2.0; + // diameter in screen points + return self.userLocation.location.horizontalAccuracy / [self.mapView metersPerPointAtLatitude:self.userLocation.coordinate.latitude] * 2.0; } - (UIImage *)headingIndicatorTintedGradientImage diff --git a/platform/ios/src/MGLMapView.h b/platform/ios/src/MGLMapView.h index 64d2e53d21..c3ffe1983e 100644 --- a/platform/ios/src/MGLMapView.h +++ b/platform/ios/src/MGLMapView.h @@ -778,6 +778,23 @@ MGL_EXPORT IB_DESIGNABLE - (void)setCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion; /** + Moves the viewpoint to a different location with respect to the map with an + optional transition duration and timing function. + + @param camera The new viewpoint. + @param duration The amount of time, measured in seconds, that the transition + animation should take. Specify `0` to jump to the new viewpoint + instantaneously. + @param function A timing function used for the animation. Set this parameter to + `nil` for a transition that matches most system animations. If the duration + is `0`, this parameter is ignored. + @param edgePadding The minimum padding (in screen points) that would be visible + around the returned camera object if it were set as the receiver’s camera. + @param completion The block to execute after the animation finishes. + */ +- (void)setCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function edgePadding:(UIEdgeInsets)edgePadding completionHandler:(nullable void (^)(void))completion; + +/** Moves the viewpoint to a different location using a transition animation that evokes powered flight and a default duration based on the length of the flight path. diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 9c3d1d415f..d9d03ea478 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -1116,8 +1116,10 @@ public: - (void)updateTintColorForView:(UIView *)view { - // stop at recursing container & annotation views (#8522) - if ([view isEqual:self.annotationContainerView]) return; + // Don't update: + // - annotation views + // - attribution button (handled automatically) + if ([view isEqual:self.annotationContainerView] || [view isEqual:self.attributionButton]) return; if ([view respondsToSelector:@selector(setTintColor:)]) view.tintColor = self.tintColor; @@ -1250,8 +1252,6 @@ public: { if ( ! self.isZoomEnabled) return; - if (_mbglMap->getZoom() <= _mbglMap->getMinZoom() && pinch.scale < 1) return; - _mbglMap->cancelTransitions(); CGPoint centerPoint = [self anchorPointForGesture:pinch]; @@ -1267,17 +1267,17 @@ public: } else if (pinch.state == UIGestureRecognizerStateChanged) { + // Zoom limiting happens at the core level. CGFloat newScale = self.scale * pinch.scale; - double zoom = log2(newScale); - if (zoom < _mbglMap->getMinZoom()) return; - + double newZoom = log2(newScale); + // Calculates the final camera zoom, has no effect within current map camera. - MGLMapCamera *toCamera = [self cameraByZoomingToZoomLevel:zoom aroundAnchorPoint:centerPoint]; + MGLMapCamera *toCamera = [self cameraByZoomingToZoomLevel:newZoom aroundAnchorPoint:centerPoint]; if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] || [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera]) { - _mbglMap->setZoom(zoom, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }); + _mbglMap->setZoom(newZoom, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }); // The gesture recognizer only reports the gesture’s current center // point, so use the previous center point to anchor the transition. // If the number of touches has changed, the remembered center point is @@ -1625,9 +1625,9 @@ public: { CGFloat distance = [quickZoom locationInView:quickZoom.view].y - self.quickZoomStart; - CGFloat newZoom = log2f(self.scale) + (distance / 75); + CGFloat newZoom = MAX(log2f(self.scale) + (distance / 75), _mbglMap->getMinZoom()); - if (newZoom < _mbglMap->getMinZoom()) return; + if (_mbglMap->getZoom() == newZoom) return; CGPoint centerPoint = [self anchorPointForGesture:quickZoom]; @@ -1760,39 +1760,6 @@ public: return [gesture locationInView:gesture.view]; } -- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer -{ - if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) - { - UIPanGestureRecognizer *panGesture = (UIPanGestureRecognizer *)gestureRecognizer; - - if (panGesture.minimumNumberOfTouches == 2) - { - CGPoint velocity = [panGesture velocityInView:panGesture.view]; - double gestureAngle = MGLDegreesFromRadians(atan(velocity.y / velocity.x)); - double horizontalToleranceDegrees = 20.0; - - // cancel if gesture angle is not 90º±20º (more or less vertical) - if ( ! (fabs((fabs(gestureAngle) - 90.0)) < horizontalToleranceDegrees)) - { - return NO; - } - } - } - else if (gestureRecognizer == _singleTapGestureRecognizer) - { - // Gesture will be recognized if it could deselect an annotation - if(!self.selectedAnnotation) - { - id<MGLAnnotation>annotation = [self annotationForGestureRecognizer:(UITapGestureRecognizer*)gestureRecognizer persistingResults:NO]; - if(!annotation) { - return NO; - } - } - } - return YES; -} - - (void)handleCalloutAccessoryTapGesture:(UITapGestureRecognizer *)tap { if ([self.delegate respondsToSelector:@selector(mapView:annotation:calloutAccessoryControlTapped:)]) @@ -1836,12 +1803,60 @@ public: UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, calloutView); } +- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer +{ + if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) + { + UIPanGestureRecognizer *panGesture = (UIPanGestureRecognizer *)gestureRecognizer; + + if (panGesture.minimumNumberOfTouches == 2) + { + CGPoint west = [panGesture locationOfTouch:0 inView:panGesture.view]; + CGPoint east = [panGesture locationOfTouch:1 inView:panGesture.view]; + + if (west.x > east.x) { + CGPoint swap = west; + west = east; + east = swap; + } + + CLLocationDegrees horizontalToleranceDegrees = 60.0; + if ([self angleBetweenPoints:west east:east] > horizontalToleranceDegrees) { + return NO; + } + + } + } + else if (gestureRecognizer == _singleTapGestureRecognizer) + { + // Gesture will be recognized if it could deselect an annotation + if(!self.selectedAnnotation) + { + id<MGLAnnotation>annotation = [self annotationForGestureRecognizer:(UITapGestureRecognizer*)gestureRecognizer persistingResults:NO]; + if(!annotation) { + return NO; + } + } + } + return YES; +} + - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { NSArray *validSimultaneousGestures = @[ self.pan, self.pinch, self.rotate ]; return ([validSimultaneousGestures containsObject:gestureRecognizer] && [validSimultaneousGestures containsObject:otherGestureRecognizer]); } + +- (CLLocationDegrees)angleBetweenPoints:(CGPoint)west east:(CGPoint)east +{ + CGFloat slope = (west.y - east.y) / (west.x - east.x); + + CGFloat angle = atan(fabs(slope)); + CLLocationDegrees degrees = MGLDegreesFromRadians(angle); + + return degrees; +} - (void)trackGestureEvent:(NSString *)gestureID forRecognizer:(UIGestureRecognizer *)recognizer { @@ -2743,6 +2758,10 @@ public: - (void)setCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion { + [self setCamera:camera withDuration:duration animationTimingFunction:function edgePadding:self.contentInset completionHandler:completion]; +} + +- (void)setCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function edgePadding:(UIEdgeInsets)edgePadding completionHandler:(nullable void (^)(void))completion { mbgl::AnimationOptions animationOptions; if (duration > 0) { @@ -2771,7 +2790,7 @@ public: [self willChangeValueForKey:@"camera"]; _mbglMap->cancelTransitions(); - mbgl::CameraOptions cameraOptions = [self cameraOptionsObjectForAnimatingToCamera:camera edgePadding:self.contentInset]; + mbgl::CameraOptions cameraOptions = [self cameraOptionsObjectForAnimatingToCamera:camera edgePadding:edgePadding]; _mbglMap->easeTo(cameraOptions, animationOptions); [self didChangeValueForKey:@"camera"]; } |