diff --git a/platform/ios/app/MBXAnnotationView.m b/platform/ios/app/MBXAnnotationView.m index 890881a3162..6925358a30c 100644 --- a/platform/ios/app/MBXAnnotationView.m +++ b/platform/ios/app/MBXAnnotationView.m @@ -25,4 +25,16 @@ - (void)setCenterColor:(UIColor *)centerColor { } } +- (nullable id)actionForLayer:(CALayer *)layer forKey:(NSString *)event +{ + if ([event isEqualToString:@"position"]) + { + CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:event]; + animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; + animation.speed = 0.1; + return animation; + } + return [super actionForLayer:layer forKey:event]; +} + @end diff --git a/platform/ios/src/MGLAnnotationView.mm b/platform/ios/src/MGLAnnotationView.mm index 4f16eb32586..a63114273bd 100644 --- a/platform/ios/src/MGLAnnotationView.mm +++ b/platform/ios/src/MGLAnnotationView.mm @@ -98,7 +98,7 @@ - (void)updateScaleForPitch:(CGFloat)pitch - (id)actionForLayer:(CALayer *)layer forKey:(NSString *)event { // Allow mbgl to drive animation of this view’s bounds. - if ([event isEqualToString:@"bounds"]) + if ([event isEqualToString:@"bounds"] || [event isEqualToString:@"position"]) { return [NSNull null]; } diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index cde877407ba..a677aacca71 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -1774,12 +1774,19 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag); NSString *symbolName; - if (!annotationContext.annotationView) + if (annotationContext.annotationView) + { + // Redundantly move the associated annotation view outside the scope of the animation-less transaction block in -updateAnnotationViews. + CGPoint center = [self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self]; + [annotationContext.annotationView setCenter:center pitch:self.camera.pitch]; + } + else { MGLAnnotationImage *annotationImage = [self imageOfAnnotationWithTag:annotationTag]; symbolName = annotationImage.styleIconIdentifier; } + // Update the annotation’s backing geometry to match the annotation model object. Any associated annotation view is also moved by side effect. However, -updateAnnotationViews disables the view’s animation actions, because it can’t distinguish between moves due to the viewport changing and moves due to the annotation’s coordinate changing. _mbglMap->updateAnnotation(annotationTag, mbgl::SymbolAnnotation { point, symbolName.UTF8String ?: "" }); if (annotationTag == _selectedAnnotationTag) { @@ -4470,6 +4477,9 @@ - (void)updateAnnotationViews return; } + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + for (auto &pair : _annotationContextsByAnnotationTag) { CGRect viewPort = CGRectInset(self.bounds, -_largestAnnotationViewSize.width - MGLAnnotationUpdateViewportOutset.width, -_largestAnnotationViewSize.height - MGLAnnotationUpdateViewportOutset.width); @@ -4506,6 +4516,8 @@ - (void)updateAnnotationViews [annotationView setCenter:center pitch:self.camera.pitch]; } } + + [CATransaction commit]; } - (void)enqueueAnnotationViewForAnnotationContext:(MGLAnnotationContext &)annotationContext