| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- //
- // ApexMapView.m
- // OpenStreetMap
- //
- // Created by Jack on 2019/1/18.
- // Copyright © 2019 Jack Template. All rights reserved.
- //
- #import "ApexMapView.h"
- #import "UIView+RAConstraint.h"
- //static NSString * const kTileSource = @"https://map.apexshipping.com/osm_tiles/{z}/{x}/{y}.png";
- //static NSString * const kTileSource = @"https://map.apexshipping.com/osmmt/{z}/{x}/{y}.png";
- static NSString * const kTileSource = @"https://map.apexshipping.com/osmhd/{z}/{x}/{y}.png";
- static int const tileSize = 512;
- static NSString * const kOpenStreetMapURL = @"https://www.openstreetmap.org/copyright";
- static NSString * const kCopyright = @"OpenStreetMap";
- @interface ApexMapView () <MKMapViewDelegate>
- @property (nonatomic,strong) UIButton *legalBtn;
- @property (nonatomic,strong) MKTileOverlay *tileOverlay;
- @property (nonatomic,weak) id<MKMapViewDelegate> internalDelegate;
- @end
- @implementation ApexMapView
- #pragma mark - Initial
- - (instancetype)initWithFrame:(CGRect)frame {
- if (self = [super initWithFrame:frame]) {
- [self setupMapView];
- }
- return self;
- }
- - (void)awakeFromNib {
- [super awakeFromNib];
- [self setupMapView];
- }
- - (void)setupMapView {
-
- self.rotateEnabled = NO;
- [self apex_setDelegate:self];
-
- [self addOverlay:self.tileOverlay];
-
- // if (@available(iOS 13.0, *)) {
- // MKMapCameraZoomRange* zoom_range =[[MKMapCameraZoomRange alloc] initWithMinCenterCoordinateDistance:500];
- // // [[MKMapCameraZoomRange alloc] initWithMinCenterCoordinateDistance:-1 maxCenterCoordinateDistance:10];
- // [self setCameraZoomRange:zoom_range];
- // } else {
- // // Fallback on earlier versions
- // }
- }
- - (void)layoutSubviews {
- [super layoutSubviews];
-
- NSArray<UIView *> *subViews = self.subviews;
- for (UIView *subView in subViews) {
-
- if ([subView isMemberOfClass:NSClassFromString(@"MKAttributionLabel")]) {
- [subView removeFromSuperview];
- } else if ([subView isMemberOfClass:[UIImageView class]]) {
- [subView removeFromSuperview];
- }
- }
- if (![subViews containsObject:self.legalBtn]) {
- [self setupLegalView];
- }
- }
- - (void)setupLegalView {
-
- [self addSubview:self.legalBtn];
-
- [self.legalBtn ra_applyConstraints:^(RAConstraintMaker *maker) {
-
- maker.left.ra_equalTo(self.left).ra_offset(5.0f);
- maker.bottom.ra_equalTo(self.bottom).ra_offset(-5.0f);
- }];
-
- }
- #pragma mark - Override
- - (void)setDelegate:(id<MKMapViewDelegate>)delegate {
- if (delegate) {
- __weak typeof(delegate) weakDelegate = delegate;
- _internalDelegate = weakDelegate;
- } else {
- _internalDelegate = nil;
- }
- }
- - (void)apex_setDelegate:(id<MKMapViewDelegate>)delegate {
- [super setDelegate:delegate];
- }
- #pragma mark - Getter
- //- (double) zoomLevel {
- //
- ////
- //// double d= 360 * self.frame.size.width /256/self.region.span.longitudeDelta;
- //// return log2(d);
- ////
- // MKCoordinateRegion region = self.region;
- //
- // double centerPixelX = [MKMapView longitudeToPixelSpaceX: region.center.longitude];
- // double topLeftPixelX = [MKMapView longitudeToPixelSpaceX: region.center.longitude - region.span.longitudeDelta / 2];
- //
- // double scaledMapWidth = (centerPixelX - topLeftPixelX) * 2;
- // CGSize mapSizeInPixels = self.bounds.size;
- // double zoomScale = scaledMapWidth / mapSizeInPixels.width;
- // double zoomExponent = log(zoomScale/(512/256)) / log(2);
- // double zoomLevel = 20 - zoomExponent;
- //
- // return zoomLevel;
- //}
- - (MKTileOverlay *)tileOverlay {
- if (!_tileOverlay) {
- _tileOverlay = [[MKTileOverlay alloc] initWithURLTemplate:kTileSource];
- _tileOverlay.canReplaceMapContent = YES;
- _tileOverlay.minimumZ = 0;
- _tileOverlay.maximumZ = 18;
- _tileOverlay.tileSize = CGSizeMake(tileSize, tileSize);
- }
- return _tileOverlay;
- }
- - (UIButton *)legalBtn {
- if (!_legalBtn) {
- _legalBtn = [UIButton buttonWithType:UIButtonTypeSystem];
- _legalBtn.titleLabel.font = [UIFont systemFontOfSize:12.0f];
- [_legalBtn setTitle:kCopyright forState:UIControlStateNormal];
- [_legalBtn addTarget:self action:@selector(legalButtonDidClick:) forControlEvents:UIControlEventTouchUpInside];
- }
- return _legalBtn;
- }
- #pragma mark - User Action
- - (void)legalButtonDidClick:(id)sender {
-
- NSURL *url = [NSURL URLWithString:kOpenStreetMapURL];
- if ([[UIApplication sharedApplication] canOpenURL:url]) {
- if (@available(iOS 10, *)) {
- [[UIApplication sharedApplication] openURL:url options:@{UIApplicationOpenURLOptionsSourceApplicationKey: @YES} completionHandler:^(BOOL success) {
-
- }];
- } else{
- [[UIApplication sharedApplication] openURL:url];
- }
- }
- }
- #pragma mark - MKMapViewDelegate
- - (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:regionWillChangeAnimated:)]) {
- [_internalDelegate mapView:mapView regionWillChangeAnimated:animated];
- }
- }
- - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
-
- double z=[self zoomLevel];
- double pi =3.1415926;
- int x= floor((mapView.centerCoordinate.longitude + 180) / 360 * pow(2 , z));
- int y= floor((1 - log(tan(mapView.centerCoordinate.latitude * pi / 180) + 1 / cos(mapView.centerCoordinate.latitude * pi / 180)) / pi) / 2 * pow(2 , z));
- NSLog(@"地图控件完成了改变 x:%d,y:%d,z:%f",x,y,z);
- if(mapView.zoomLevel>18)
- {
-
- NSLog(@"地图控件完成了改变 zoom to 18");
- [mapView setCenterCoordinate:mapView.centerCoordinate zoomLevel:18 animated:true];
- }
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:regionDidChangeAnimated:)]) {
- [_internalDelegate mapView:mapView regionDidChangeAnimated:animated];
- }
- }
- - (void)mapViewDidChangeVisibleRegion:(MKMapView *)mapView {
-
- // double z=[self zoomLevel];
- //
- // double pi =3.1415926;
- // int x= floor((mapView.centerCoordinate.longitude + 180) / 360 * pow(2 , z));
- //
- // int y= floor((1 - log(tan(mapView.centerCoordinate.latitude * pi / 180) + 1 / cos(mapView.centerCoordinate.latitude * pi / 180)) / pi) / 2 * pow(2 , z));
- //
- // NSLog(@"地图控件完成了改变 x:%d,y:%d,z:%f",x,y,z);
- //
- // if((int)z>18)
- // {
- //
- //
- // [mapView setCenterCoordinate:mapView.centerCoordinate zoomLevel:18 animated:true];
- //
- // }
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapViewDidChangeVisibleRegion:)]) {
- [_internalDelegate mapViewDidChangeVisibleRegion:mapView];
- }
- }
- - (void)mapViewWillStartLoadingMap:(MKMapView *)mapView {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapViewWillStartLoadingMap:)]) {
- [_internalDelegate mapViewWillStartLoadingMap:mapView];
- }
- }
- - (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapViewDidFinishLoadingMap:)]) {
- [_internalDelegate mapViewDidFinishLoadingMap:mapView];
- }
- }
- - (void)mapViewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapViewDidFailLoadingMap:withError:)]) {
- [_internalDelegate mapViewDidFailLoadingMap:mapView withError:error];
- }
- }
- - (void)mapViewWillStartRenderingMap:(MKMapView *)mapView {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapViewWillStartRenderingMap:)]) {
- [_internalDelegate mapViewWillStartRenderingMap:mapView];
- }
- }
- - (void)mapViewDidFinishRenderingMap:(MKMapView *)mapView fullyRendered:(BOOL)fullyRendered {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapViewDidFinishRenderingMap:fullyRendered:)]) {
- [_internalDelegate mapViewDidFinishRenderingMap:mapView fullyRendered:fullyRendered];
- }
- }
- // mapView:viewForAnnotation: provides the view for each annotation.
- // This method may be called for all or some of the added annotations.
- // For MapKit provided annotations (eg. MKUserLocation) return nil to use the MapKit provided annotation view.
- - (nullable MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:viewForAnnotation:)]) {
- return [_internalDelegate mapView:mapView viewForAnnotation:annotation];
- }
- return nil;
- }
- // mapView:didAddAnnotationViews: is called after the annotation views have been added and positioned in the map.
- // The delegate can implement this method to animate the adding of the annotations views.
- // Use the current positions of the annotation views as the destinations of the animation.
- - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray<MKAnnotationView *> *)views {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:didAddAnnotationViews:)]) {
- [_internalDelegate mapView:mapView didAddAnnotationViews:views];
- }
- }
- #if TARGET_OS_IPHONE
- // mapView:annotationView:calloutAccessoryControlTapped: is called when the user taps on left & right callout accessory UIControls.
- - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:annotationView:calloutAccessoryControlTapped:)]) {
- [_internalDelegate mapView:mapView annotationView:view calloutAccessoryControlTapped:control];
- }
- }
- #endif
- - (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:didSelectAnnotationView:)]) {
- [_internalDelegate mapView:mapView didSelectAnnotationView:view];
- }
- }
- - (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:didDeselectAnnotationView:)]) {
- [_internalDelegate mapView:mapView didDeselectAnnotationView:view];
- }
- }
- - (void)mapViewWillStartLocatingUser:(MKMapView *)mapView {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapViewWillStartLocatingUser:)]) {
- [_internalDelegate mapViewWillStartLocatingUser:mapView];
- }
- }
- - (void)mapViewDidStopLocatingUser:(MKMapView *)mapView {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapViewDidStopLocatingUser:)]) {
- [_internalDelegate mapViewDidStopLocatingUser:mapView];
- }
- }
- - (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:didUpdateUserLocation:)]) {
- [_internalDelegate mapView:mapView didUpdateUserLocation:userLocation];
- }
- }
- - (void)mapView:(MKMapView *)mapView didFailToLocateUserWithError:(NSError *)error {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:didFailToLocateUserWithError:)]) {
- [_internalDelegate mapView:mapView didFailToLocateUserWithError:error];
- }
- }
- - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view didChangeDragState:(MKAnnotationViewDragState)newState
- fromOldState:(MKAnnotationViewDragState)oldState {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:annotationView:didChangeDragState:fromOldState:)]) {
- [_internalDelegate mapView:mapView annotationView:view didChangeDragState:newState fromOldState:oldState];
- }
- }
- #if TARGET_OS_IPHONE
- - (void)mapView:(MKMapView *)mapView didChangeUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:didChangeUserTrackingMode:animated:)]) {
- [_internalDelegate mapView:mapView didChangeUserTrackingMode:mode animated:animated];
- }
- }
- #endif
- - (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id <MKOverlay>)overlay {
-
- if (overlay == self.tileOverlay) {
-
- return [[MKTileOverlayRenderer alloc] initWithTileOverlay:overlay];
- } else {
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:rendererForOverlay:)]) {
- return [_internalDelegate mapView:mapView rendererForOverlay:overlay];
- } else {
- return nil;
- }
- }
- }
- - (void)mapView:(MKMapView *)mapView didAddOverlayRenderers:(NSArray<MKOverlayRenderer *> *)renderers {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:didAddOverlayRenderers:)]) {
- [_internalDelegate mapView:mapView didAddOverlayRenderers:renderers];
- }
- }
- #if TARGET_OS_IPHONE
- // Prefer -mapView:rendererForOverlay:
- - (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay {
-
- if (overlay == self.tileOverlay) {
-
- return [[MKOverlayView alloc] initWithOverlay:overlay];
- } else {
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:viewForOverlay:)]) {
- return [_internalDelegate mapView:mapView viewForOverlay:overlay];
- } else {
- return nil;
- }
- }
- }
- // Called after the provided overlay views have been added and positioned in the map.
- // Prefer -mapView:didAddOverlayRenderers:
- - (void)mapView:(MKMapView *)mapView didAddOverlayViews:(NSArray *)overlayViews {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:didAddOverlayViews:)]) {
- [_internalDelegate mapView:mapView didAddOverlayViews:overlayViews];
- }
- }
- #endif
- // Return nil for default MKClusterAnnotation, it is illegal to return a cluster annotation not containing the identical array of member annotations given.
- - (MKClusterAnnotation *)mapView:(MKMapView *)mapView clusterAnnotationForMemberAnnotations:(NSArray<id<MKAnnotation>>*)memberAnnotations {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:clusterAnnotationForMemberAnnotations:)]) {
- return [_internalDelegate mapView:mapView clusterAnnotationForMemberAnnotations:memberAnnotations];
- }
- return nil;
- }
- @end
|