Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Tracking modes for non-user annotations #5645

Closed
erichoracek opened this issue Jul 11, 2016 · 7 comments
Closed

Tracking modes for non-user annotations #5645

erichoracek opened this issue Jul 11, 2016 · 7 comments
Labels
annotations Annotations on iOS and macOS or markers on Android archived Archived because of inactivity feature iOS Mapbox Maps SDK for iOS

Comments

@erichoracek
Copy link
Contributor

erichoracek commented Jul 11, 2016

We would like to have the ability to have the map track an arbitrary annotation similarly to the options currently available for the user annotation (the MGLUserTrackingMode options), which add linear animations that track changes to the user's location. It follows that there would be a tracking option to animatedly zoom to fit both the user annotation and another arbitrary point annotation within the map bounds.

Alongside this change, it would make sense to have changes to -[MGLAnnotation coordinate] animated on the map along with the animated map region updates (just like the user annotation).

The reasoning that we'd like to do this is that we're receiving frequent location updates from a websocket and want to smoothly animate them on a map (think uber, lyft, etc.).

@1ec5 1ec5 added feature iOS Mapbox Maps SDK for iOS annotations Annotations on iOS and macOS or markers on Android labels Jul 11, 2016
@1ec5
Copy link
Contributor

1ec5 commented Jul 11, 2016

Alongside this change, it would make sense to have changes to -[MGLAnnotation coordinate] animated on the map along with the animated map region updates (just like the user annotation).

That’s possible as of #5550, which is in the latest v3.3.0 release candidate. An MGLAnnotationView can be animated implicitly using Core Animation. We’ll have an example up on the SDK’s website once we publish the final release.

Is a dedicated “annotation tracking mode” API necessary? If you need to animate the map as an annotation’s coordinate changes, you can call -[MGLMapView setCamera:withDuration:animationTimingFunction:] each time you change the coordinate. That’s essentially what the SDK does on each user location update.

@erichoracek
Copy link
Contributor Author

After trying out this approach I get some very strange behavior when animating alongside the -setCamera:withDuration:animationTimingFunction: approach. See this video for what I mean. This is with the following code:

NSTimeInterval duration = [currentLocation.timestamp 
    timeIntervalSinceDate:previousLocation.timestamp];

MGLMapCamera *camera = [MGLMapCamera
    cameraLookingAtCenterCoordinate:currentLocation.coordinate
    fromDistance:1000.0
    pitch:0.0
    heading:0.0];

CAMediaTimingFunction *timingFunction = [CAMediaTimingFunction 
    functionWithName:kCAMediaTimingFunctionLinear];

[self.mapView
    setCamera:camera
    withDuration:duration
    animationTimingFunction:timingFunction];

self.annotationView.duration = duration;
annotation.coordinate = currentLocation.coordinate;

In the MGLAnnotationView subclass:

- (nullable id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event {
    if ([event isEqualToString:@"transform"] || [event isEqualToString:@"position"]) {
        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:event];
        animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
        animation.duration = self.duration;
        return animation;
    }

    return [super actionForLayer:layer forKey:event];
}

@erichoracek
Copy link
Contributor Author

For more context, the behavior I'm trying to replicate is identical to that of the user annotation but exclusively using the public-facing APIs and with an MGLPointAnnotation/MGLAnnotationView combination.

The MGLAnnotationView implicit animations seem to work well as long as the map isn't moving. However, once the map is panned/zoomed or animated via the setCamera: methods, the animation of the annotation is no longer in sync with movements of the map.

The test I'm using to try this out is hooking up a point annotation to a CLLocationManager and seeing whether or not it smoothly overlays on top of the user annotation when showsUserLocation = YES. This isn't the real scenario we want, but serves as a good way to test map animations and user interactions when we have a custom annotation since we can use the user annotation as a reference.

@1ec5
Copy link
Contributor

1ec5 commented Jul 12, 2016

That’s an interesting effect. It looks as though the annotation does animate, but with a different duration or easing than the map (can’t tell which).

The built-in user tracking mode does a slight of hand, as explained in #3589: the user location annotation view is actually affixed to the middle of the view, independently of the user location annotation’s logical position. You could replicate that effect in your own code by implementing -[MGLMapViewDelegate mapViewDidFinishRenderingFrame:fullyRendered:] to set the view’s center to the map view’s center. (The implicit animation described above would be unnecessary.)

For more context, the behavior I'm trying to replicate is identical to that of the user annotation but exclusively using the public-facing APIs and with an MGLPointAnnotation/MGLAnnotationView combination.

Is the intent to have an actual user location annotation but customize its appearance? We’re building that functionality in #5573, so you’d be able to specify an annotation view for the user location annotation and not worry about all the other details.

@erichoracek
Copy link
Contributor Author

To clear things up, the intent is to add an annotation to the map with a coordinate backed by a stream of locations that are driven by a socket connection with a server, rather than the user location itself. In our scenario, this location is that of a car.

With respect to tracking modes, the intent is that the vehicle location would be tracked equivalently to MGLUserTrackingModeFollow until the user interacts with the map, at which point the vehicle location would continue to animate, but the user would be free to move the map around. In this state, the user can re-enable the tracking mode at any time by tapping a button.

Regarding the implicit animation, something like that would still be necessary (as far as I can tell from reading through the implementation of MGLMapView). In MGLMapView an animation occurs on the user annotation regardless of whether the map is centered or not. This happens at MGLMapView.mm#L4659-L4673. In this scenario, userPoint can either be the center of the map or the current location if there's no tracking mode.

Regardless, I think the "slight of hand" you're referencing (pinning the annotation to the center of a map in a tracking mode) is a non-obvious solution to the issue of wanting to track an arbitrary annotation on the map. This is a perfect example of why an API that is specifically aimed at tracking an arbitrary annotation would be useful.

@1ec5
Copy link
Contributor

1ec5 commented Jul 12, 2016

Thanks for the clarification. That makes sense now.

Regardless, I think the "slight of hand" you're referencing (pinning the annotation to the center of a map in a tracking mode) is a non-obvious solution to the issue of wanting to track an arbitrary annotation on the map. This is a perfect example of why an API that is specifically aimed at tracking an arbitrary annotation would be useful.

You’ve got a point there, but we’ll definitely need to think this API through a bit more. The user tracking mode implementation is very closely tied to CLLocationManager’s design and behavior. Off the top of my head, the animation assumes that locations generally come in once a second, but it looks like you’re accounting for that in your code above.

@stale
Copy link

stale bot commented Nov 20, 2018

This issue has been automatically detected as stale because it has not had recent activity and will be archived. Thank you for your contributions.

@stale stale bot closed this as completed Nov 20, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
annotations Annotations on iOS and macOS or markers on Android archived Archived because of inactivity feature iOS Mapbox Maps SDK for iOS
Projects
None yet
Development

No branches or pull requests

2 participants