Files
MapLibreParticleLab/platform/ios/src/MLNCompassButton.mm
Bart Louwers 2a8ebc4906 core: rename mbgl directories to mln (#4511)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-08-22 20:50:14 +02:00

150 lines
4.6 KiB
Plaintext

#import "MLNCompassButton_Private.h"
#import "MLNCompassDirectionFormatter.h"
#import "MLNGeometry.h"
#import "MLNMapView_Private.h"
#import "NSBundle+MLNAdditions.h"
#import "UIImage+MLNAdditions.h"
#include <mln/math/wrap.hpp>
@interface MLNCompassButton ()
@property (nonatomic, weak) MLNMapView *mapView;
@property (nonatomic) MLNCompassDirectionFormatter *accessibilityCompassFormatter;
@end
@implementation MLNCompassButton
+ (instancetype)compassButtonWithMapView:(MLNMapView *)mapView {
return [[MLNCompassButton alloc] initWithMapView:mapView];
}
- (instancetype)initWithMapView:(MLNMapView *)mapView {
if (self = [super init]) {
self.mapView = mapView;
[self commonInit];
}
return self;
}
- (void)commonInit {
self.image = self.compassImage;
self.compassVisibility = MLNOrnamentVisibilityAdaptive;
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 = [[MLNCompassDirectionFormatter alloc] init];
self.accessibilityCompassFormatter.unitStyle = NSFormattingUnitStyleLong;
[self sizeToFit];
}
- (void)setCompassVisibility:(MLNOrnamentVisibility)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}];
UIFont *northFont;
if (@available(iOS 13.0, *)) {
northFont = [UIFont systemFontOfSize:11 weight:UIFontWeightLight];
} else {
northFont = [UIFont systemFontOfSize:11 weight:UIFontWeightUltraLight];
}
NSAttributedString *north = [[NSAttributedString alloc]
initWithString:NSLocalizedStringWithDefaultValue(@"COMPASS_NORTH", nil, nil, @"N",
@"Compass abbreviation for north")
attributes:@{
NSFontAttributeName : northFont,
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 = mln::util::wrap(-direction, 0., 360.);
self.transform = CGAffineTransformMakeRotation(MLNRadiansFromDegrees(plateDirection));
self.isAccessibilityElement = direction > 0;
self.accessibilityValue = [self.accessibilityCompassFormatter stringFromDirection:direction];
switch (self.compassVisibility) {
case MLNOrnamentVisibilityAdaptive:
if (direction > 0 && self.alpha < 1) {
[self showCompass:animated];
} else if (direction == 0 && self.alpha > 0) {
[self hideCompass:animated];
}
break;
case MLNOrnamentVisibilityVisible:
[self showCompass:animated];
break;
case MLNOrnamentVisibilityHidden:
[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];
self.isAccessibilityElement = NO;
self.accessibilityElementsHidden = YES;
}
- (void)animateToAlpha:(CGFloat)alpha {
[UIView animateWithDuration:MLNAnimationDuration
delay:0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
self.alpha = alpha;
}
completion:nil];
}
@end