summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMinh Nguyễn <mxn@1ec5.org>2016-06-05 13:29:23 -0700
committerMinh Nguyễn <mxn@1ec5.org>2016-07-02 21:00:41 -0700
commitbb2f627b1287483749487e405931d3cbe2c5363e (patch)
tree27d1e359f8bc289532810a28b92d3240b13a6216
parentbb4606b53de1ae06cff81d7f05be31d163b78f86 (diff)
downloadqtlocation-mapboxgl-bb2f627b1287483749487e405931d3cbe2c5363e.tar.gz
[ios] Made annotation view position animatable
We don’t normally want an annotation view to animate its position, because that makes the view appear to lag behind the map. But when the annotation view moves due to the underlying annotation model object moving, the developer may want exactly that effect. This change continues to disable the default implicit bounds (and now position) animation. It also groups the view updates in -updateAnnotationViews in a transaction that disables animation actions, to improve perceived performance with a large number of annotations. However, when the annotation model object changes, we move the annotation view outside of that transaction to allow the developer to opt into animation. If the developer moreover wants the annotation view to animate even due to the viewport changing, they can override -setCenter: to use a UIView animation block. Fixes #5230.
-rw-r--r--platform/ios/app/MBXAnnotationView.m13
-rw-r--r--platform/ios/src/MGLAnnotationView.mm2
-rw-r--r--platform/ios/src/MGLMapView.mm18
3 files changed, 29 insertions, 4 deletions
diff --git a/platform/ios/app/MBXAnnotationView.m b/platform/ios/app/MBXAnnotationView.m
index c181211431..82af15314a 100644
--- a/platform/ios/app/MBXAnnotationView.m
+++ b/platform/ios/app/MBXAnnotationView.m
@@ -51,6 +51,7 @@
case MGLAnnotationViewDragStateCanceling:
break;
case MGLAnnotationViewDragStateEnding: {
+ self.transform = CGAffineTransformScale(CGAffineTransformIdentity, 2, 2);
[UIView animateWithDuration:.4 delay:0 usingSpringWithDamping:.4 initialSpringVelocity:.5 options:UIViewAnimationOptionCurveLinear animations:^{
self.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1, 1);
} completion:nil];
@@ -60,5 +61,17 @@
}
+- (nullable id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event
+{
+ if (([event isEqualToString:@"transform"] || [event isEqualToString:@"position"])
+ && self.dragState == MGLAnnotationViewDragStateNone)
+ {
+ 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 a1e93de108..494253b561 100644
--- a/platform/ios/src/MGLAnnotationView.mm
+++ b/platform/ios/src/MGLAnnotationView.mm
@@ -243,7 +243,7 @@
- (id<CAAction>)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 5c0d8d2a59..d7115d0a56 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -1773,11 +1773,18 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
{
const mbgl::Point<double> point = MGLPointFromLocationCoordinate2D(annotation.coordinate);
- NSString *symbolName;
+ MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag);
+ if (annotationContext.annotationView)
+ {
+ // Redundantly move the associated annotation view outside the scope of the animation-less transaction block in -updateAnnotationViews.
+ annotationContext.annotationView.center = [self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self];
+ }
+
MGLAnnotationImage *annotationImage = [self imageOfAnnotationWithTag:annotationTag];
- symbolName = annotationImage.styleIconIdentifier;
+ NSString *symbolName = annotationImage.styleIconIdentifier;
- _mbglMap->updateAnnotation(annotationTag, mbgl::SymbolAnnotation { point, symbolName.UTF8String});
+ // 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)
{
[self deselectAnnotation:annotation animated:YES];
@@ -4556,6 +4563,9 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
return;
}
+ [CATransaction begin];
+ [CATransaction setDisableActions:YES];
+
for (auto &pair : _annotationContextsByAnnotationTag)
{
CGRect viewPort = CGRectInset(self.bounds,
@@ -4592,6 +4602,8 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
annotationView.center = [self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self];
}
}
+
+ [CATransaction commit];
}
- (void)enqueueAnnotationViewForAnnotationContext:(MGLAnnotationContext &)annotationContext