summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin R. Miller <incanus@users.noreply.github.com>2015-03-27 12:02:13 -0700
committerJustin R. Miller <incanus@users.noreply.github.com>2015-03-27 12:02:13 -0700
commit8dc42df41115735f939243b2d77633f013794ecd (patch)
treea02532ff052e2717adddfa11c9f9698db9b39f2b
parentcaf970eab72fbcc21a48c0ed6ccfbce2458bd224 (diff)
parent215a7c4b2b1222f953efaf814041253b1a561725 (diff)
downloadqtlocation-mapboxgl-8dc42df41115735f939243b2d77633f013794ecd.tar.gz
Merge pull request #1141 from mapbox/tighten-gestures
tighten up gestures & metrics
-rw-r--r--platform/ios/MGLMapView.mm199
1 files changed, 101 insertions, 98 deletions
diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm
index 6f3aec8038..200fb02fa7 100644
--- a/platform/ios/MGLMapView.mm
+++ b/platform/ios/MGLMapView.mm
@@ -586,14 +586,14 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr;
- (void)handlePanGesture:(UIPanGestureRecognizer *)pan
{
- [self trackGestureEvent:MGLEventGesturePanStart forRecognizer:pan];
-
if ( ! self.isScrollEnabled) return;
mbglMap->cancelTransitions();
if (pan.state == UIGestureRecognizerStateBegan)
{
+ [self trackGestureEvent:MGLEventGesturePanStart forRecognizer:pan];
+
self.centerPoint = CGPointMake(0, 0);
self.userTrackingMode = MGLUserTrackingModeNone;
@@ -663,8 +663,6 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr;
- (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinch
{
- [self trackGestureEvent:MGLEventGesturePinchStart forRecognizer:pinch];
-
if ( ! self.isZoomEnabled) return;
if (mbglMap->getZoom() <= mbglMap->getMinZoom() && pinch.scale < 1) return;
@@ -673,6 +671,8 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr;
if (pinch.state == UIGestureRecognizerStateBegan)
{
+ [self trackGestureEvent:MGLEventGesturePinchStart forRecognizer:pinch];
+
mbglMap->startScaling();
self.scale = mbglMap->getScale();
@@ -701,14 +701,14 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr;
- (void)handleRotateGesture:(UIRotationGestureRecognizer *)rotate
{
- [self trackGestureEvent:MGLEventGestureRotateStart forRecognizer:rotate];
-
if ( ! self.isRotateEnabled) return;
mbglMap->cancelTransitions();
if (rotate.state == UIGestureRecognizerStateBegan)
{
+ [self trackGestureEvent:MGLEventGestureRotateStart forRecognizer:rotate];
+
mbglMap->startRotating();
self.angle = [MGLMapView degreesToRadians:mbglMap->getBearing()] * -1;
@@ -743,137 +743,140 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr;
- (void)handleSingleTapGesture:(UITapGestureRecognizer *)singleTap
{
- [self trackGestureEvent:MGLEventGestureSingleTap forRecognizer:singleTap];
-
- CGPoint tapPoint = [singleTap locationInView:self];
-
- if (self.userLocationVisible && ! [self.selectedAnnotation isEqual:self.userLocation])
+ if (singleTap.state == UIGestureRecognizerStateEnded)
{
- CGRect userLocationRect = CGRectMake(tapPoint.x - 15, tapPoint.y - 15, 30, 30);
+ [self trackGestureEvent:MGLEventGestureSingleTap forRecognizer:singleTap];
+
+ CGPoint tapPoint = [singleTap locationInView:self];
- if (CGRectContainsPoint(userLocationRect, [self convertCoordinate:self.userLocation.coordinate toPointToView:self]))
+ if (self.userLocationVisible && ! [self.selectedAnnotation isEqual:self.userLocation])
{
- [self selectAnnotation:self.userLocation animated:YES];
- return;
+ CGRect userLocationRect = CGRectMake(tapPoint.x - 15, tapPoint.y - 15, 30, 30);
+
+ if (CGRectContainsPoint(userLocationRect, [self convertCoordinate:self.userLocation.coordinate toPointToView:self]))
+ {
+ [self selectAnnotation:self.userLocation animated:YES];
+ return;
+ }
}
- }
- // tolerances based on touch size & typical marker aspect ratio
- CGFloat toleranceWidth = 40;
- CGFloat toleranceHeight = 60;
+ // tolerances based on touch size & typical marker aspect ratio
+ CGFloat toleranceWidth = 40;
+ CGFloat toleranceHeight = 60;
- // setup a recognition area weighted 2/3 of the way above the point to account for average marker imagery
- CGRect tapRect = CGRectMake(tapPoint.x - toleranceWidth / 2, tapPoint.y - 2 * toleranceHeight / 3, toleranceWidth, toleranceHeight);
- CGPoint tapRectLowerLeft = CGPointMake(tapRect.origin.x, tapRect.origin.y + tapRect.size.height);
- CGPoint tapRectUpperLeft = CGPointMake(tapRect.origin.x, tapRect.origin.y);
- CGPoint tapRectUpperRight = CGPointMake(tapRect.origin.x + tapRect.size.width, tapRect.origin.y);
- CGPoint tapRectLowerRight = CGPointMake(tapRect.origin.x + tapRect.size.width, tapRect.origin.y + tapRect.size.height);
+ // setup a recognition area weighted 2/3 of the way above the point to account for average marker imagery
+ CGRect tapRect = CGRectMake(tapPoint.x - toleranceWidth / 2, tapPoint.y - 2 * toleranceHeight / 3, toleranceWidth, toleranceHeight);
+ CGPoint tapRectLowerLeft = CGPointMake(tapRect.origin.x, tapRect.origin.y + tapRect.size.height);
+ CGPoint tapRectUpperLeft = CGPointMake(tapRect.origin.x, tapRect.origin.y);
+ CGPoint tapRectUpperRight = CGPointMake(tapRect.origin.x + tapRect.size.width, tapRect.origin.y);
+ CGPoint tapRectLowerRight = CGPointMake(tapRect.origin.x + tapRect.size.width, tapRect.origin.y + tapRect.size.height);
- // figure out what that means in coordinate space
- CLLocationCoordinate2D coordinate;
- mbgl::LatLngBounds tapBounds;
+ // figure out what that means in coordinate space
+ CLLocationCoordinate2D coordinate;
+ mbgl::LatLngBounds tapBounds;
- coordinate = [self convertPoint:tapRectLowerLeft toCoordinateFromView:self];
- tapBounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude));
+ coordinate = [self convertPoint:tapRectLowerLeft toCoordinateFromView:self];
+ tapBounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude));
- coordinate = [self convertPoint:tapRectUpperLeft toCoordinateFromView:self];
- tapBounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude));
+ coordinate = [self convertPoint:tapRectUpperLeft toCoordinateFromView:self];
+ tapBounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude));
- coordinate = [self convertPoint:tapRectUpperRight toCoordinateFromView:self];
- tapBounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude));
+ coordinate = [self convertPoint:tapRectUpperRight toCoordinateFromView:self];
+ tapBounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude));
- coordinate = [self convertPoint:tapRectLowerRight toCoordinateFromView:self];
- tapBounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude));
+ coordinate = [self convertPoint:tapRectLowerRight toCoordinateFromView:self];
+ tapBounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude));
- // query for nearby annotations
- std::vector<uint32_t> nearbyAnnotations = mbglMap->getAnnotationsInBounds(tapBounds);
+ // query for nearby annotations
+ std::vector<uint32_t> nearbyAnnotations = mbglMap->getAnnotationsInBounds(tapBounds);
- int32_t newSelectedAnnotationID = -1;
+ int32_t newSelectedAnnotationID = -1;
- if (nearbyAnnotations.size())
- {
- // there is at least one nearby annotation; select one
- //
- // first, sort for comparison and iteration
- std::sort(nearbyAnnotations.begin(), nearbyAnnotations.end());
-
- if (nearbyAnnotations == self.annotationsNearbyLastTap)
+ if (nearbyAnnotations.size())
{
- // the selection candidates haven't changed; cycle through them
- if (self.selectedAnnotation &&
- [[[self.annotationIDsByAnnotation objectForKey:self.selectedAnnotation]
- objectForKey:MGLAnnotationIDKey] unsignedIntValue] == self.annotationsNearbyLastTap.back())
- {
- // the selected annotation is the last in the set; cycle back to the first
- // note: this could be the selected annotation if only one in set
- newSelectedAnnotationID = self.annotationsNearbyLastTap.front();
- }
- else if (self.selectedAnnotation)
+ // there is at least one nearby annotation; select one
+ //
+ // first, sort for comparison and iteration
+ std::sort(nearbyAnnotations.begin(), nearbyAnnotations.end());
+
+ if (nearbyAnnotations == self.annotationsNearbyLastTap)
{
- // otherwise increment the selection through the candidates
- uint32_t currentID = [[[self.annotationIDsByAnnotation objectForKey:self.selectedAnnotation] objectForKey:MGLAnnotationIDKey] unsignedIntValue];
- auto result = std::find(self.annotationsNearbyLastTap.begin(), self.annotationsNearbyLastTap.end(), currentID);
- auto distance = std::distance(self.annotationsNearbyLastTap.begin(), result);
- newSelectedAnnotationID = self.annotationsNearbyLastTap[distance + 1];
+ // the selection candidates haven't changed; cycle through them
+ if (self.selectedAnnotation &&
+ [[[self.annotationIDsByAnnotation objectForKey:self.selectedAnnotation]
+ objectForKey:MGLAnnotationIDKey] unsignedIntValue] == self.annotationsNearbyLastTap.back())
+ {
+ // the selected annotation is the last in the set; cycle back to the first
+ // note: this could be the selected annotation if only one in set
+ newSelectedAnnotationID = self.annotationsNearbyLastTap.front();
+ }
+ else if (self.selectedAnnotation)
+ {
+ // otherwise increment the selection through the candidates
+ uint32_t currentID = [[[self.annotationIDsByAnnotation objectForKey:self.selectedAnnotation] objectForKey:MGLAnnotationIDKey] unsignedIntValue];
+ auto result = std::find(self.annotationsNearbyLastTap.begin(), self.annotationsNearbyLastTap.end(), currentID);
+ auto distance = std::distance(self.annotationsNearbyLastTap.begin(), result);
+ newSelectedAnnotationID = self.annotationsNearbyLastTap[distance + 1];
+ }
+ else
+ {
+ // no current selection; select the first one
+ newSelectedAnnotationID = self.annotationsNearbyLastTap.front();
+ }
}
else
{
- // no current selection; select the first one
+ // start tracking a new set of nearby annotations
+ self.annotationsNearbyLastTap = nearbyAnnotations;
+
+ // select the first one
newSelectedAnnotationID = self.annotationsNearbyLastTap.front();
}
}
else
{
- // start tracking a new set of nearby annotations
- self.annotationsNearbyLastTap = nearbyAnnotations;
-
- // select the first one
- newSelectedAnnotationID = self.annotationsNearbyLastTap.front();
+ // there are no nearby annotations; deselect if necessary
+ newSelectedAnnotationID = -1;
}
- }
- else
- {
- // there are no nearby annotations; deselect if necessary
- newSelectedAnnotationID = -1;
- }
- if (newSelectedAnnotationID >= 0)
- {
- // find & select model object for selection
- NSEnumerator *enumerator = self.annotationIDsByAnnotation.keyEnumerator;
-
- while (id <MGLAnnotation> annotation = enumerator.nextObject)
+ if (newSelectedAnnotationID >= 0)
{
- if ([[[self.annotationIDsByAnnotation objectForKey:annotation] objectForKey:MGLAnnotationIDKey] integerValue] == newSelectedAnnotationID)
+ // find & select model object for selection
+ NSEnumerator *enumerator = self.annotationIDsByAnnotation.keyEnumerator;
+
+ while (id <MGLAnnotation> annotation = enumerator.nextObject)
{
- // only change selection status if not the currently selected annotation
- if ( ! [annotation isEqual:self.selectedAnnotation])
+ if ([[[self.annotationIDsByAnnotation objectForKey:annotation] objectForKey:MGLAnnotationIDKey] integerValue] == newSelectedAnnotationID)
{
- [self selectAnnotation:annotation animated:YES];
- }
+ // only change selection status if not the currently selected annotation
+ if ( ! [annotation isEqual:self.selectedAnnotation])
+ {
+ [self selectAnnotation:annotation animated:YES];
+ }
- // either way, we should stop enumerating
- break;
+ // either way, we should stop enumerating
+ break;
+ }
}
}
- }
- else
- {
- // deselect any selected annotation
- if (self.selectedAnnotation) [self deselectAnnotation:self.selectedAnnotation animated:YES];
+ else
+ {
+ // deselect any selected annotation
+ if (self.selectedAnnotation) [self deselectAnnotation:self.selectedAnnotation animated:YES];
+ }
}
}
- (void)handleDoubleTapGesture:(UITapGestureRecognizer *)doubleTap
{
- [self trackGestureEvent:MGLEventGestureDoubleTap forRecognizer:doubleTap];
-
if ( ! self.isZoomEnabled) return;
mbglMap->cancelTransitions();
if (doubleTap.state == UIGestureRecognizerStateBegan)
{
+ [self trackGestureEvent:MGLEventGestureDoubleTap forRecognizer:doubleTap];
+
self.userTrackingMode = MGLUserTrackingModeNone;
}
else if (doubleTap.state == UIGestureRecognizerStateEnded)
@@ -897,8 +900,6 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr;
- (void)handleTwoFingerTapGesture:(UITapGestureRecognizer *)twoFingerTap
{
- [self trackGestureEvent:MGLEventGestureTwoFingerSingleTap forRecognizer:twoFingerTap];
-
if ( ! self.isZoomEnabled) return;
if (mbglMap->getZoom() == mbglMap->getMinZoom()) return;
@@ -907,6 +908,8 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr;
if (twoFingerTap.state == UIGestureRecognizerStateBegan)
{
+ [self trackGestureEvent:MGLEventGestureTwoFingerSingleTap forRecognizer:twoFingerTap];
+
self.userTrackingMode = MGLUserTrackingModeNone;
}
else if (twoFingerTap.state == UIGestureRecognizerStateEnded)
@@ -930,14 +933,14 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr;
- (void)handleQuickZoomGesture:(UILongPressGestureRecognizer *)quickZoom
{
- [self trackGestureEvent:MGLEventGestureQuickZoom forRecognizer:quickZoom];
-
if ( ! self.isZoomEnabled) return;
mbglMap->cancelTransitions();
if (quickZoom.state == UIGestureRecognizerStateBegan)
{
+ [self trackGestureEvent:MGLEventGestureQuickZoom forRecognizer:quickZoom];
+
self.scale = mbglMap->getScale();
self.quickZoomStart = [quickZoom locationInView:quickZoom.view].y;