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

Refactored iOS annotation selection #3261

Merged
merged 3 commits into from
Dec 14, 2015
Merged

Refactored iOS annotation selection #3261

merged 3 commits into from
Dec 14, 2015

Conversation

1ec5
Copy link
Contributor

@1ec5 1ec5 commented Dec 11, 2015

This PR backports a lot of annotation-related improvements from the OS X port in #3135, reprising a large chunk of #1496. MGLMapView now maps “annotation tags” (Cocoa-speak for numeric annotation IDs, by analogy with view tags, tooltip tags, etc.) to context objects that pair annotations with their identifiers. Previously, MGLMapView mapped the annotation objects themselves to context objects that contained annotation IDs, but this caused most operations involving annotations to be rather expensive: since mbgl tracks annotations by ID, most of the time you know the ID and need either the annotation or some piece of metadata about it.

Tapping now selects annotations more reliably. Tapping near the top of a large annotation image now selects that annotation. An annotation image’s alignment insets influence how far away the user can tap and still select the annotation. For example, if your annotation image has a large shadow, you can keep that shadow from being tappable by excluding it from the image’s alignment rect. Hit testing now works much like in #3135, with the exception that UIKit doesn’t support hit testing based on pixel opacity.

@RomainQuidet, I was focused on porting existing changes and haven’t worked out how this PR affects #3220. In principle, both changes would be desirable because mine improves interaction with the annotation after it’s added, while yours affects the annotation’s placement in the first place. Let me know if you have any concerns.

The selection code uses std::remove_if() instead of mbgl::util::erase_if(), fixing #3206 but not the underlying crash. @jfirebaugh, is there a reason to keep erase_if() around? It seems to crash when there are a lot of elements and a lot of them are deleted.

The user dot’s callout view is now centered above the user dot. It was previously offset slightly to the left.

More geographic methods have been added internally. -convertRect:toLatLngBoundsFromView: returns a world-spanning bounds when the world is wrapping.

Fixes #1504, fixes #3027, fixes #3159, fixes #3206.

/cc @incanus @friedbunny

@1ec5 1ec5 added bug iOS Mapbox Maps SDK for iOS refactor labels Dec 11, 2015
@1ec5 1ec5 self-assigned this Dec 11, 2015
@1ec5 1ec5 added this to the ios-v3.1.0 milestone Dec 11, 2015
@1ec5
Copy link
Contributor Author

1ec5 commented Dec 11, 2015

If you tap near a tight cluster of annotations, the annotation directly beneath your finger should be selected first. Previously, the annotations within the query bounds would be selected in order from oldest to newest, which was counterintuitive. The new behavior does sometimes make it more difficult to cycle through the entire cluster, but the previous behavior often got in the way anyways, as your finger would wind up atop a callout view for an annotation farther south. @incanus, since you’re more familiar with the old behavior, let me know if there are problems with the new approach.

@1ec5 1ec5 mentioned this pull request Dec 11, 2015
8 tasks
return self.annotationImagesByIdentifier[identifier];
}

/** Returns the straight-line distance between two coordinates. */
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn’t quite true. This function returns a value that correlates weakly to the distance between two coordinates. It’s only useful for sorting coordinates by proximity on the screen without going through the trouble of converting back and forth between screen and geographic coordinates. I’ll probably just inline it.

MGLMapView now maps “annotation tags” (Cocoa-speak for numeric annotation IDs) to context objects that pair annotations with their identifiers. Previously, MGLMapView mapped the annotation objects themselves to context objects that contained annotation IDs, but this caused most operations involving annotations to be rather expensive: since mbgl tracks annotations by ID, most of the time you know the ID and need either the annotation or some piece of metadata about it.

Along for the ride, geographic methods and support for alignment rect insets on annotation images have been ported from #3135 for OS X. Hit testing now works much like in #3135, with the exception that UIKit doesn’t support hit testing based on pixel opacity. -convertRect:toLatLngBoundsFromView: returns a world-spanning bounds when the world is wrapping.

Fixes #3159.
Decreased hit test padding for annotation selection, since the query no longer depends on it. Fixed an assertion failure when selecting an annotation while the user dot is selected. Fixed an issue where selecting a selected user dot deselected it. Fixed an issue where the user dot’s callout positioning rect was off-center and a little too high.
If you tap near a tight cluster of annotations, the annotation directly beneath your finger should be selected first. Previously, the annotations within the query bounds would be selected in order from oldest to newest, which was counterintuitive. The new behavior does sometimes make it more difficult to cycle through the entire cluster, but the previous behavior often got in the way anyways, as your finger would wind up atop a callout view for an annotation farther south.

Also updated the changelog.
@1ec5 1ec5 merged commit b59f087 into master Dec 14, 2015
@1ec5 1ec5 removed the in progress label Dec 14, 2015
1ec5 added a commit that referenced this pull request Dec 14, 2015
@1ec5 1ec5 deleted the 1ec5-annotation-tag-3159 branch December 14, 2015 01:29
1ec5 added a commit that referenced this pull request Feb 11, 2016
After filtering out elements of a vector using std::remove_if(), it’s apparently necessary to resize the vector. Otherwise, removing only has the effect of shifting the non-matching items to the end of the vector. This change reduces the annotation tap target back to almost what it was before #3261, except that these days the target is centered around the annotation image rather than the center point. There remains a much smaller slop area around the annotation, but nothing close to the effective padding before this change.

Fixes #3880.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.