1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#import "MGLCompassButton_Private.h"
#import "MGLCompassDirectionFormatter.h"
#import <Mapbox/MGLGeometry.h>
#import "MGLMapView_Private.h"
#import "UIImage+MGLAdditions.h"
#import "NSBundle+MGLAdditions.h"
#include <mbgl/math/wrap.hpp>
@interface MGLCompassButton ()
@property (nonatomic, weak) MGLMapView *mapView;
@property (nonatomic) MGLCompassDirectionFormatter *accessibilityCompassFormatter;
@end
@implementation MGLCompassButton
+ (instancetype)compassButtonWithMapView:(MGLMapView *)mapView {
return [[MGLCompassButton alloc] initWithMapView:mapView];
}
- (instancetype)initWithMapView:(MGLMapView *)mapView {
if (self = [super init]) {
self.mapView = mapView;
[self commonInit];
}
return self;
}
- (void)commonInit {
self.image = self.compassImage;
self.compassVisibility = MGLOrnamentVisibilityAdaptive;
self.alpha = 0;
self.userInteractionEnabled = YES;
self.translatesAutoresizingMaskIntoConstraints = NO;
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
[self addGestureRecognizer:tapGesture];
self.accessibilityTraits = UIAccessibilityTraitButton;
self.accessibilityLabel = NSLocalizedStringWithDefaultValue(@"COMPASS_A11Y_LABEL", nil, nil, @"Compass", @"Accessibility label");
self.accessibilityHint = NSLocalizedStringWithDefaultValue(@"COMPASS_A11Y_HINT", nil, nil, @"Rotates the map to face due north", @"Accessibility hint");
self.accessibilityCompassFormatter = [[MGLCompassDirectionFormatter alloc] init];
self.accessibilityCompassFormatter.unitStyle = NSFormattingUnitStyleLong;
[self sizeToFit];
}
- (void)setCompassVisibility:(MGLOrnamentVisibility)compassVisibility {
if (_compassVisibility == compassVisibility) { return; }
_compassVisibility = compassVisibility;
[self updateCompassAnimated:NO];
}
- (UIImage *)compassImage {
UIImage *scaleImage = [UIImage mgl_resourceImageNamed:@"Compass"];
UIGraphicsBeginImageContextWithOptions(scaleImage.size, NO, UIScreen.mainScreen.scale);
[scaleImage drawInRect:{CGPointZero, scaleImage.size}];
NSAttributedString *north = [[NSAttributedString alloc] initWithString:NSLocalizedStringWithDefaultValue(@"COMPASS_NORTH", nil, nil, @"N", @"Compass abbreviation for north") attributes:@{
NSFontAttributeName: [UIFont systemFontOfSize:11 weight:UIFontWeightUltraLight],
NSForegroundColorAttributeName: [UIColor whiteColor],
}];
CGRect stringRect = CGRectMake((scaleImage.size.width - north.size.width) / 2,
scaleImage.size.height * 0.435,
north.size.width, north.size.height);
[north drawInRect:stringRect];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
- (void)handleTapGesture:(__unused UITapGestureRecognizer *)sender {
[self.mapView resetNorth];
}
- (void)updateCompass {
[self updateCompassAnimated:YES];
}
- (void)updateCompassAnimated:(BOOL)animated {
CLLocationDirection direction = self.mapView.direction;
CLLocationDirection plateDirection = mbgl::util::wrap(-direction, 0., 360.);
self.transform = CGAffineTransformMakeRotation(MGLRadiansFromDegrees(plateDirection));
self.isAccessibilityElement = direction > 0;
self.accessibilityValue = [self.accessibilityCompassFormatter stringFromDirection:direction];
switch (self.compassVisibility) {
case MGLOrnamentVisibilityAdaptive:
if (direction > 0 && self.alpha < 1) {
[self showCompass:animated];
} else if (direction == 0 && self.alpha > 0) {
[self hideCompass:animated];
}
break;
case MGLOrnamentVisibilityVisible:
[self showCompass:animated];
break;
case MGLOrnamentVisibilityHidden:
[self hideCompass:animated];
break;
}
}
- (void)showCompass:(BOOL)animated {
animated ? [self animateToAlpha:1] : [self setAlpha:1];
}
- (void)hideCompass:(BOOL)animated {
animated ? [self animateToAlpha:0] : [self setAlpha:0];
}
- (void)animateToAlpha:(CGFloat)alpha {
[UIView animateWithDuration:MGLAnimationDuration delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
self.alpha = alpha;
} completion:nil];
}
@end
|