diff options
author | Justin R. Miller <incanus@users.noreply.github.com> | 2015-03-27 12:02:13 -0700 |
---|---|---|
committer | Justin R. Miller <incanus@users.noreply.github.com> | 2015-03-27 12:02:13 -0700 |
commit | 8dc42df41115735f939243b2d77633f013794ecd (patch) | |
tree | a02532ff052e2717adddfa11c9f9698db9b39f2b | |
parent | caf970eab72fbcc21a48c0ed6ccfbce2458bd224 (diff) | |
parent | 215a7c4b2b1222f953efaf814041253b1a561725 (diff) | |
download | qtlocation-mapboxgl-8dc42df41115735f939243b2d77633f013794ecd.tar.gz |
Merge pull request #1141 from mapbox/tighten-gestures
tighten up gestures & metrics
-rw-r--r-- | platform/ios/MGLMapView.mm | 199 |
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; |