...
|
...
|
@@ -935,9 +935,6 @@ |
|
|
myOrigin.y = myOrigin.y - (zoomRect.size.height / 2);
|
|
|
zoomRect.origin = myOrigin;
|
|
|
|
|
|
RMProjectedPoint topRight = RMProjectedPointMake(myOrigin.x + zoomRect.size.width, myOrigin.y + zoomRect.size.height);
|
|
|
RMLog(@"zoomWithBoundingBox: {%f,%f} - {%f,%f}", [_projection projectedPointToCoordinate:myOrigin].longitude, [_projection projectedPointToCoordinate:myOrigin].latitude, [_projection projectedPointToCoordinate:topRight].longitude, [_projection projectedPointToCoordinate:topRight].latitude);
|
|
|
|
|
|
[self setProjectedBounds:zoomRect animated:animated];
|
|
|
}
|
|
|
}
|
...
|
...
|
@@ -2438,16 +2435,16 @@ |
|
|
{
|
|
|
if (newShowsUserLocation == showsUserLocation)
|
|
|
return;
|
|
|
|
|
|
|
|
|
showsUserLocation = newShowsUserLocation;
|
|
|
|
|
|
|
|
|
if (newShowsUserLocation)
|
|
|
{
|
|
|
if (_delegateHasWillStartLocatingUser)
|
|
|
[_delegate mapViewWillStartLocatingUser:self];
|
|
|
|
|
|
|
|
|
self.userLocation = [RMUserLocation annotationWithMapView:self coordinate:CLLocationCoordinate2DMake(0, 0) andTitle:nil];
|
|
|
|
|
|
|
|
|
locationManager = [[CLLocationManager alloc] init];
|
|
|
locationManager.headingFilter = 5;
|
|
|
locationManager.delegate = self;
|
...
|
...
|
@@ -2460,14 +2457,14 @@ |
|
|
locationManager.delegate = nil;
|
|
|
[locationManager release];
|
|
|
locationManager = nil;
|
|
|
|
|
|
|
|
|
if (_delegateHasDidStopLocatingUser)
|
|
|
[_delegate mapViewDidStopLocatingUser:self];
|
|
|
|
|
|
|
|
|
[self setUserTrackingMode:RMUserTrackingModeNone animated:YES];
|
|
|
|
|
|
|
|
|
NSMutableArray *annotationsToRemove = [NSMutableArray array];
|
|
|
|
|
|
|
|
|
for (RMAnnotation *annotation in _annotations)
|
|
|
if (annotation.isUserLocationAnnotation)
|
|
|
[annotationsToRemove addObject:annotation];
|
...
|
...
|
@@ -2493,15 +2490,15 @@ |
|
|
if (userLocation)
|
|
|
{
|
|
|
CGPoint locationPoint = [self mapPositionForAnnotation:userLocation];
|
|
|
|
|
|
|
|
|
CGRect locationRect = CGRectMake(locationPoint.x - userLocation.location.horizontalAccuracy,
|
|
|
locationPoint.y - userLocation.location.horizontalAccuracy,
|
|
|
userLocation.location.horizontalAccuracy * 2,
|
|
|
userLocation.location.horizontalAccuracy * 2);
|
|
|
|
|
|
|
|
|
return CGRectIntersectsRect([self bounds], locationRect);
|
|
|
}
|
|
|
|
|
|
|
|
|
return NO;
|
|
|
}
|
|
|
|
...
|
...
|
@@ -2514,9 +2511,9 @@ |
|
|
{
|
|
|
if (mode == userTrackingMode)
|
|
|
return;
|
|
|
|
|
|
|
|
|
userTrackingMode = mode;
|
|
|
|
|
|
|
|
|
switch (userTrackingMode)
|
|
|
{
|
|
|
case RMUserTrackingModeNone:
|
...
|
...
|
@@ -2533,8 +2530,10 @@ |
|
|
_overlayView.transform = CGAffineTransformIdentity;
|
|
|
|
|
|
for (RMAnnotation *annotation in _annotations)
|
|
|
{
|
|
|
if ( ! annotation.isUserLocationAnnotation)
|
|
|
annotation.layer.transform = CATransform3DIdentity;
|
|
|
}
|
|
|
}
|
|
|
completion:nil];
|
|
|
|
...
|
...
|
@@ -2545,15 +2544,15 @@ |
|
|
[userHeadingTrackingView removeFromSuperview];
|
|
|
userHeadingTrackingView = nil;
|
|
|
}
|
|
|
|
|
|
|
|
|
userLocation.layer.hidden = NO;
|
|
|
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
case RMUserTrackingModeFollow:
|
|
|
{
|
|
|
self.showsUserLocation = YES;
|
|
|
|
|
|
|
|
|
[locationManager stopUpdatingHeading];
|
|
|
|
|
|
if (self.userLocation)
|
...
|
...
|
@@ -2566,7 +2565,7 @@ |
|
|
[userHeadingTrackingView removeFromSuperview];
|
|
|
userHeadingTrackingView = nil;
|
|
|
}
|
|
|
|
|
|
|
|
|
[UIView animateWithDuration:(animated ? 0.5 : 0.0)
|
|
|
delay:0.0
|
|
|
options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationCurveEaseInOut
|
...
|
...
|
@@ -2574,41 +2573,43 @@ |
|
|
{
|
|
|
_mapScrollView.transform = CGAffineTransformIdentity;
|
|
|
_overlayView.transform = CGAffineTransformIdentity;
|
|
|
|
|
|
|
|
|
for (RMAnnotation *annotation in _annotations)
|
|
|
{
|
|
|
if ( ! annotation.isUserLocationAnnotation)
|
|
|
annotation.layer.transform = CATransform3DIdentity;
|
|
|
}
|
|
|
}
|
|
|
completion:nil];
|
|
|
|
|
|
|
|
|
userLocation.layer.hidden = NO;
|
|
|
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
case RMUserTrackingModeFollowWithHeading:
|
|
|
{
|
|
|
self.showsUserLocation = YES;
|
|
|
|
|
|
|
|
|
userLocation.layer.hidden = YES;
|
|
|
|
|
|
|
|
|
userHeadingTrackingView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"HeadingAngleSmall.png"]];
|
|
|
|
|
|
|
|
|
userHeadingTrackingView.center = CGPointMake(round([self bounds].size.width / 2),
|
|
|
round([self bounds].size.height / 2) - (userHeadingTrackingView.bounds.size.height / 2) - 4);
|
|
|
|
|
|
|
|
|
userHeadingTrackingView.alpha = 0.0;
|
|
|
|
|
|
|
|
|
[self addSubview:userHeadingTrackingView];
|
|
|
|
|
|
|
|
|
[UIView animateWithDuration:0.5 animations:^(void) { userHeadingTrackingView.alpha = 1.0; }];
|
|
|
|
|
|
|
|
|
userLocationTrackingView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"TrackingDot.png"]];
|
|
|
|
|
|
|
|
|
userLocationTrackingView.center = CGPointMake(round([self bounds].size.width / 2),
|
|
|
round([self bounds].size.height / 2));
|
|
|
|
|
|
|
|
|
[self addSubview:userLocationTrackingView];
|
|
|
|
|
|
|
|
|
if (self.zoom < 3)
|
|
|
[self zoomByFactor:exp2f(3 - [self zoom]) near:self.center animated:YES];
|
|
|
|
...
|
...
|
@@ -2616,7 +2617,7 @@ |
|
|
[self locationManager:locationManager didUpdateToLocation:self.userLocation.location fromLocation:self.userLocation.location];
|
|
|
|
|
|
[locationManager startUpdatingHeading];
|
|
|
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
}
|
...
|
...
|
@@ -2629,7 +2630,7 @@ |
|
|
{
|
|
|
if ( ! showsUserLocation || _mapScrollView.isDragging)
|
|
|
return;
|
|
|
|
|
|
|
|
|
if ([newLocation distanceFromLocation:oldLocation])
|
|
|
{
|
|
|
userLocation.location = newLocation;
|
...
|
...
|
@@ -2637,7 +2638,7 @@ |
|
|
if (_delegateHasDidUpdateUserLocation)
|
|
|
[_delegate mapView:self didUpdateUserLocation:userLocation];
|
|
|
}
|
|
|
|
|
|
|
|
|
if (self.userTrackingMode != RMUserTrackingModeNone)
|
|
|
{
|
|
|
// zoom centered on user location unless we're already centered there (or very close)
|
...
|
...
|
@@ -2648,7 +2649,7 @@ |
|
|
if (fabsf(userLocationPoint.x - mapCenterPoint.x) > 2 || fabsf(userLocationPoint.y - mapCenterPoint.y > 2))
|
|
|
{
|
|
|
float delta = newLocation.horizontalAccuracy / 110000; // approx. meter per degree latitude
|
|
|
|
|
|
|
|
|
CLLocationCoordinate2D southWest = CLLocationCoordinate2DMake(newLocation.coordinate.latitude - delta,
|
|
|
newLocation.coordinate.longitude - delta);
|
|
|
|
...
|
...
|
@@ -2664,105 +2665,94 @@ |
|
|
}
|
|
|
|
|
|
RMAnnotation *accuracyCircleAnnotation = nil;
|
|
|
|
|
|
|
|
|
for (RMAnnotation *annotation in _annotations)
|
|
|
{
|
|
|
if ([annotation.annotationType isEqualToString:kRMAccuracyCircleAnnotationTypeName])
|
|
|
accuracyCircleAnnotation = annotation;
|
|
|
|
|
|
}
|
|
|
|
|
|
if ( ! accuracyCircleAnnotation)
|
|
|
{
|
|
|
accuracyCircleAnnotation = [RMAnnotation annotationWithMapView:self coordinate:newLocation.coordinate andTitle:nil];
|
|
|
|
|
|
accuracyCircleAnnotation.annotationType = kRMAccuracyCircleAnnotationTypeName;
|
|
|
|
|
|
accuracyCircleAnnotation.clusteringEnabled = NO;
|
|
|
|
|
|
accuracyCircleAnnotation.layer = [[RMCircle alloc] initWithView:self radiusInMeters:newLocation.horizontalAccuracy];
|
|
|
|
|
|
accuracyCircleAnnotation.isUserLocationAnnotation = YES;
|
|
|
|
|
|
|
|
|
((RMCircle *)accuracyCircleAnnotation.layer).lineColor = [UIColor colorWithRed:0.378 green:0.552 blue:0.827 alpha:0.7];
|
|
|
((RMCircle *)accuracyCircleAnnotation.layer).fillColor = [UIColor colorWithRed:0.378 green:0.552 blue:0.827 alpha:0.15];
|
|
|
|
|
|
|
|
|
((RMCircle *)accuracyCircleAnnotation.layer).lineWidthInPixels = 2.0;
|
|
|
|
|
|
|
|
|
[self addAnnotation:accuracyCircleAnnotation];
|
|
|
}
|
|
|
|
|
|
|
|
|
if ([newLocation distanceFromLocation:oldLocation])
|
|
|
accuracyCircleAnnotation.coordinate = newLocation.coordinate;
|
|
|
|
|
|
|
|
|
if (newLocation.horizontalAccuracy != oldLocation.horizontalAccuracy)
|
|
|
((RMCircle *)accuracyCircleAnnotation.layer).radiusInMeters = newLocation.horizontalAccuracy;
|
|
|
|
|
|
RMAnnotation *trackingHaloAnnotation = nil;
|
|
|
|
|
|
|
|
|
for (RMAnnotation *annotation in _annotations)
|
|
|
{
|
|
|
if ([annotation.annotationType isEqualToString:kRMTrackingHaloAnnotationTypeName])
|
|
|
trackingHaloAnnotation = annotation;
|
|
|
|
|
|
}
|
|
|
|
|
|
if ( ! trackingHaloAnnotation)
|
|
|
{
|
|
|
trackingHaloAnnotation = [RMAnnotation annotationWithMapView:self coordinate:newLocation.coordinate andTitle:nil];
|
|
|
|
|
|
trackingHaloAnnotation.annotationType = kRMTrackingHaloAnnotationTypeName;
|
|
|
|
|
|
trackingHaloAnnotation.clusteringEnabled = NO;
|
|
|
|
|
|
|
|
|
// create image marker
|
|
|
//
|
|
|
trackingHaloAnnotation.layer = [[RMMarker alloc] initWithUIImage:[UIImage imageNamed:@"TrackingDotHalo.png"]];
|
|
|
|
|
|
trackingHaloAnnotation.isUserLocationAnnotation = YES;
|
|
|
|
|
|
|
|
|
[CATransaction begin];
|
|
|
[CATransaction setAnimationDuration:2.5];
|
|
|
[CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
|
|
|
|
|
|
|
|
|
// scale out radially
|
|
|
//
|
|
|
CABasicAnimation *boundsAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
|
|
|
|
|
|
boundsAnimation.repeatCount = MAXFLOAT;
|
|
|
|
|
|
boundsAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.1, 0.1, 1.0)];
|
|
|
boundsAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(2.0, 2.0, 1.0)];
|
|
|
|
|
|
boundsAnimation.removedOnCompletion = NO;
|
|
|
|
|
|
boundsAnimation.fillMode = kCAFillModeForwards;
|
|
|
|
|
|
|
|
|
[trackingHaloAnnotation.layer addAnimation:boundsAnimation forKey:@"animateScale"];
|
|
|
|
|
|
|
|
|
// go transparent as scaled out
|
|
|
//
|
|
|
CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
|
|
|
|
|
|
opacityAnimation.repeatCount = MAXFLOAT;
|
|
|
|
|
|
opacityAnimation.fromValue = [NSNumber numberWithFloat:1.0];
|
|
|
opacityAnimation.toValue = [NSNumber numberWithFloat:-1.0];
|
|
|
|
|
|
opacityAnimation.removedOnCompletion = NO;
|
|
|
|
|
|
opacityAnimation.fillMode = kCAFillModeForwards;
|
|
|
|
|
|
|
|
|
[trackingHaloAnnotation.layer addAnimation:opacityAnimation forKey:@"animateOpacity"];
|
|
|
|
|
|
|
|
|
[CATransaction commit];
|
|
|
|
|
|
|
|
|
[self addAnnotation:trackingHaloAnnotation];
|
|
|
}
|
|
|
|
|
|
|
|
|
if ([newLocation distanceFromLocation:oldLocation])
|
|
|
trackingHaloAnnotation.coordinate = newLocation.coordinate;
|
|
|
|
|
|
userLocation.layer.hidden = ((trackingHaloAnnotation.coordinate.latitude == 0 && trackingHaloAnnotation.coordinate.longitude == 0) || self.userTrackingMode == RMUserTrackingModeFollowWithHeading);
|
|
|
|
|
|
|
|
|
accuracyCircleAnnotation.layer.hidden = newLocation.horizontalAccuracy <= 10;
|
|
|
|
|
|
|
|
|
trackingHaloAnnotation.layer.hidden = ((trackingHaloAnnotation.coordinate.latitude == 0 && trackingHaloAnnotation.coordinate.longitude == 0) || newLocation.horizontalAccuracy > 10);
|
|
|
|
|
|
|
|
|
if ( ! [_annotations containsObject:userLocation])
|
|
|
[self addAnnotation:userLocation];
|
|
|
}
|
...
|
...
|
@@ -2776,9 +2766,9 @@ |
|
|
{
|
|
|
if ( ! showsUserLocation || _mapScrollView.isDragging)
|
|
|
return;
|
|
|
|
|
|
|
|
|
userLocation.heading = newHeading;
|
|
|
|
|
|
|
|
|
if (_delegateHasDidUpdateUserLocation)
|
|
|
[_delegate mapView:self didUpdateUserLocation:userLocation];
|
|
|
|
...
|
...
|
@@ -2787,23 +2777,25 @@ |
|
|
[CATransaction begin];
|
|
|
[CATransaction setAnimationDuration:1.0];
|
|
|
[CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
|
|
|
|
|
|
|
|
|
[UIView animateWithDuration:1.0
|
|
|
delay:0.0
|
|
|
options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationCurveEaseInOut
|
|
|
animations:^(void)
|
|
|
{
|
|
|
CGFloat angle = (M_PI / -180) * newHeading.trueHeading;
|
|
|
|
|
|
|
|
|
_mapScrollView.transform = CGAffineTransformMakeRotation(angle);
|
|
|
_overlayView.transform = CGAffineTransformMakeRotation(angle);
|
|
|
|
|
|
|
|
|
for (RMAnnotation *annotation in _annotations)
|
|
|
{
|
|
|
if ( ! annotation.isUserLocationAnnotation)
|
|
|
annotation.layer.transform = CATransform3DMakeAffineTransform(CGAffineTransformMakeRotation(-angle));
|
|
|
}
|
|
|
}
|
|
|
completion:nil];
|
|
|
|
|
|
|
|
|
[CATransaction commit];
|
|
|
}
|
|
|
}
|
...
|
...
|
@@ -2813,7 +2805,7 @@ |
|
|
if ([error code] != kCLErrorLocationUnknown)
|
|
|
{
|
|
|
self.userTrackingMode = RMUserTrackingModeNone;
|
|
|
|
|
|
|
|
|
if (_delegateHasDidFailToLocateUserWithError)
|
|
|
[_delegate mapView:self didFailToLocateUserWithError:error];
|
|
|
}
|
...
|
...
|
|