#import "MBXUserLocationAnnotationView.h" const CGFloat MBXUserLocationDotSize = 10; @implementation MBXUserLocationAnnotationView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self == nil) return nil; self.backgroundColor = [UIColor clearColor]; return self; } - (void)update { [self updateFrameWithSize:self.intrinsicContentSize]; [self setNeedsDisplay]; } - (CGSize)intrinsicContentSize { CGSize carSize = CGSizeMake(30, 60); return (self.mapView.userTrackingMode == MGLUserTrackingModeFollowWithCourse) ? carSize : [self dotSize]; } - (CGSize)dotSize { CGFloat minDotSize = 30; CGFloat dotSize = MAX(minDotSize, self.accuracyInPoints); return CGSizeMake(dotSize, dotSize); } - (void)updateFrameWithSize:(CGSize)size { if (CGSizeEqualToSize(self.frame.size, size)) return; // Update frame size, keeping the existing center point. CGRect newFrame = self.frame; CGPoint oldCenter = self.center; newFrame.size = size; self.frame = newFrame; self.center = oldCenter; } - (CGFloat)accuracyInPoints { CGFloat metersPerPoint = [self.mapView metersPerPointAtLatitude:self.userLocation.location.coordinate.latitude]; return self.userLocation.location.horizontalAccuracy / metersPerPoint; } - (void)drawRect:(CGRect)rect { (self.mapView.userTrackingMode == MGLUserTrackingModeFollowWithCourse) ? [self drawCar] : [self drawDot]; } - (void)drawDot { // Accuracy CGFloat accuracy = self.accuracyInPoints; CGFloat center = self.bounds.size.width / 2.0 - accuracy / 2.0; UIBezierPath *accuracyPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(center, center, accuracy, accuracy)]; UIColor *accuracyColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:.4]; [accuracyColor setFill]; [accuracyPath fill]; // Dot center = self.bounds.size.width / 2.0 - MBXUserLocationDotSize / 2.0; UIBezierPath *ovalPath = [UIBezierPath bezierPathWithOvalInRect: CGRectMake(center, center, MBXUserLocationDotSize, MBXUserLocationDotSize)]; [UIColor.greenColor setFill]; [ovalPath fill]; [UIColor.blackColor setStroke]; ovalPath.lineWidth = 1; [ovalPath stroke]; // Accuracy text UIFont *font = [UIFont systemFontOfSize:11]; [[NSString stringWithFormat:@"%.0f", accuracy] drawAtPoint:CGPointZero withAttributes:@{NSFontAttributeName: font, NSBackgroundColorAttributeName: [UIColor colorWithWhite:0 alpha:.5], NSForegroundColorAttributeName: [UIColor whiteColor]}]; } - (void)drawCar { UIColor* fillColor = [UIColor colorWithRed: 0 green: 0 blue: 0 alpha: 1]; UIColor* strokeColor = [UIColor colorWithRed: 0.592 green: 0.592 blue: 0.592 alpha: 1]; UIColor* fillColor2 = [UIColor colorWithRed: 1 green: 1 blue: 1 alpha: 1]; UIBezierPath* bezier2Path = [UIBezierPath bezierPath]; [bezier2Path moveToPoint: CGPointMake(30, 7.86)]; [bezier2Path addLineToPoint: CGPointMake(30, 52.66)]; [bezier2Path addCurveToPoint: CGPointMake(0, 52.66) controlPoint1: CGPointMake(30, 62.05) controlPoint2: CGPointMake(0, 62.84)]; [bezier2Path addCurveToPoint: CGPointMake(0, 7.86) controlPoint1: CGPointMake(0, 42.48) controlPoint2: CGPointMake(0, 17.89)]; [bezier2Path addCurveToPoint: CGPointMake(30, 7.86) controlPoint1: CGPointMake(-0, -2.17) controlPoint2: CGPointMake(30, -3.05)]; [bezier2Path closePath]; bezier2Path.usesEvenOddFillRule = YES; [fillColor setFill]; [bezier2Path fill]; UIBezierPath* bezier3Path = [UIBezierPath bezierPath]; [bezier3Path moveToPoint: CGPointMake(30, 7.86)]; [bezier3Path addLineToPoint: CGPointMake(30, 52.66)]; [bezier3Path addCurveToPoint: CGPointMake(0, 52.66) controlPoint1: CGPointMake(30, 62.05) controlPoint2: CGPointMake(0, 62.84)]; [bezier3Path addCurveToPoint: CGPointMake(0, 7.86) controlPoint1: CGPointMake(0, 42.48) controlPoint2: CGPointMake(0, 17.89)]; [bezier3Path addCurveToPoint: CGPointMake(30, 7.86) controlPoint1: CGPointMake(0, -2.17) controlPoint2: CGPointMake(30, -3.05)]; [bezier3Path closePath]; [strokeColor setStroke]; bezier3Path.lineWidth = 1; [bezier3Path stroke]; UIBezierPath* bezier4Path = [UIBezierPath bezierPath]; [bezier4Path moveToPoint: CGPointMake(15.56, 4.26)]; [bezier4Path addCurveToPoint: CGPointMake(26, 6) controlPoint1: CGPointMake(21, 4.26) controlPoint2: CGPointMake(26, 6)]; [bezier4Path addCurveToPoint: CGPointMake(23, 21) controlPoint1: CGPointMake(26, 6) controlPoint2: CGPointMake(29, 17)]; [bezier4Path addCurveToPoint: CGPointMake(16, 21) controlPoint1: CGPointMake(20.03, 22.98) controlPoint2: CGPointMake(16, 21)]; [bezier4Path addCurveToPoint: CGPointMake(7, 21) controlPoint1: CGPointMake(16, 21) controlPoint2: CGPointMake(9.02, 23.53)]; [bezier4Path addCurveToPoint: CGPointMake(4, 6) controlPoint1: CGPointMake(3, 16) controlPoint2: CGPointMake(4, 6)]; [bezier4Path addCurveToPoint: CGPointMake(15.56, 4.26) controlPoint1: CGPointMake(4, 6) controlPoint2: CGPointMake(10.12, 4.26)]; [bezier4Path closePath]; bezier4Path.usesEvenOddFillRule = YES; [fillColor2 setFill]; [bezier4Path fill]; UIBezierPath* rectanglePath = [UIBezierPath bezierPath]; [rectanglePath moveToPoint: CGPointMake(25, 46)]; [rectanglePath addCurveToPoint: CGPointMake(21, 55) controlPoint1: CGPointMake(31, 46) controlPoint2: CGPointMake(28.5, 55)]; [rectanglePath addCurveToPoint: CGPointMake(9, 55) controlPoint1: CGPointMake(13.5, 55) controlPoint2: CGPointMake(14, 55)]; [rectanglePath addCurveToPoint: CGPointMake(5, 46) controlPoint1: CGPointMake(4, 55) controlPoint2: CGPointMake(0, 46)]; [rectanglePath addCurveToPoint: CGPointMake(25, 46) controlPoint1: CGPointMake(10, 46) controlPoint2: CGPointMake(19, 46)]; [rectanglePath closePath]; [UIColor.whiteColor setFill]; [rectanglePath fill]; UIBezierPath* bezierPath = [UIBezierPath bezierPath]; [UIColor.whiteColor setFill]; [bezierPath fill]; UIBezierPath* rectangle2Path = [UIBezierPath bezierPath]; [rectangle2Path moveToPoint: CGPointMake(2, 35)]; [rectangle2Path addCurveToPoint: CGPointMake(4.36, 35) controlPoint1: CGPointMake(2, 39) controlPoint2: CGPointMake(4.36, 35)]; [rectangle2Path addCurveToPoint: CGPointMake(4.36, 22) controlPoint1: CGPointMake(4.36, 35) controlPoint2: CGPointMake(5.55, 26)]; [rectangle2Path addCurveToPoint: CGPointMake(2, 22) controlPoint1: CGPointMake(3.18, 18) controlPoint2: CGPointMake(2, 22)]; [rectangle2Path addCurveToPoint: CGPointMake(2, 35) controlPoint1: CGPointMake(2, 22) controlPoint2: CGPointMake(2, 31)]; [rectangle2Path closePath]; [UIColor.whiteColor setFill]; [rectangle2Path fill]; UIBezierPath* rectangle3Path = [UIBezierPath bezierPath]; [rectangle3Path moveToPoint: CGPointMake(28, 35)]; [rectangle3Path addCurveToPoint: CGPointMake(25.64, 35) controlPoint1: CGPointMake(28, 39) controlPoint2: CGPointMake(25.64, 35)]; [rectangle3Path addCurveToPoint: CGPointMake(25.64, 22) controlPoint1: CGPointMake(25.64, 35) controlPoint2: CGPointMake(24.45, 26)]; [rectangle3Path addCurveToPoint: CGPointMake(28, 22) controlPoint1: CGPointMake(26.82, 18) controlPoint2: CGPointMake(28, 22)]; [rectangle3Path addCurveToPoint: CGPointMake(28, 35) controlPoint1: CGPointMake(28, 22) controlPoint2: CGPointMake(28, 31)]; [rectangle3Path closePath]; [UIColor.whiteColor setFill]; [rectangle3Path fill]; } @end