Demo: https://github.com/xushiyou23/AMapTestingjava
轉:git
自定義類 WMSTileOverlayUtil,繼承自高德地圖接口 MATileOverlay,主要重載函數: - (NSURL *)URLForTilePath:(MATileOverlayPath)path;
- (void)loadTileAtPath:(MATileOverlayPath)path result:(void (^)(NSData *tileData, NSError *error))result;
,見代碼註釋。github
#import <Foundation/Foundation.h> #import <MAMapKit/MATileOverlay.h> @interface WMSTileOverlayUtil : MATileOverlay - (id)initWithRootURL:(NSString *)rootRUL; /** * @brief 以tile path生成URL。用於加載tile,此方法默認填充URLTemplate * @param path tile path * @return 以tile path生成tileOverlay */ - (NSURL *)URLForTilePath:(MATileOverlayPath)path; @end
#import "WMSTileOverlayUtil.h" #import <MAMapKit/MAMapKit.h> #import <AMapFoundationKit/AMapFoundationKit.h> #import <math.h> #import "Api.h" @implementation WMSTileOverlayUtil { NSString * rootURL; NSInteger titleSize; // = 256 double initialResolution; // = 156543.03392804062;//2*Math.PI*6378137/titleSize; double originShift; // = 20037508.342789244;//2*Math.PI*6378137/2.0; 周長的一半 double HALF_PI; // = Math.PI / 2.0; double RAD_PER_DEGREE; // = Math.PI / 180.0; double METER_PER_DEGREE; // = originShift / 180.0;//一度多少米 double DEGREE_PER_METER; // = 180.0 / originShift;//一米多少度 } - (id)initWithRootURL:(NSString *)rootRUL { self = [super init]; if (self) { rootURL = rootRUL; titleSize = 256; initialResolution = 156543.03392804062; originShift = 20037508.342789244; HALF_PI = M_PI_2; RAD_PER_DEGREE = M_PI / 180.0; METER_PER_DEGREE = originShift / 180.0; DEGREE_PER_METER = 180.0 / originShift; } return self; } /** * @brief 以tile path生成URL。用於加載tile,此方法默認填充URLTemplate * @param path tile path * @return 以tile path生成tileOverlay */ - (NSURL *)URLForTilePath:(MATileOverlayPath)path { NSString * strURL = [[NSString alloc] initWithFormat:@"%@%@", rootURL, [self titleBoundsByX:path.x Y:path.y Z:path.z]]; NSURL * url = [NSURL URLWithString:strURL]; return url; } /** * @brief 加載被請求的tile,並以tile數據或加載tile失敗error訪問回調block;默認實現爲首先用URLForTilePath去獲取URL,而後用異步NSURLConnection加載tile * @param path tile path * @param result 用來傳入tile數據或加載tile失敗的error訪問的回調block */ - (void)loadTileAtPath:(MATileOverlayPath)path result:(void (^)(NSData *tileData, NSError *error))result { if (path.z < 8) return; NSURL * url = [self URLForTilePath:path]; NSString * strURL = url.absoluteString; SuccessCallback successCallback = ^(id responseObject) { UIImage * image = [UIImage imageWithData:responseObject]; NSData * data = UIImagePNGRepresentation(image); result(data, nil); }; FailureCallBack failureCallBack = ^(NSError *error) { result(nil, error); }; [Api GETWMSWith:strURL successCallback:successCallback failureCallBack:failureCallBack]; } /** * @brief 取消請求瓦片,當地圖顯示區域發生變化時,會取消顯示區域外的瓦片的下載, 當disableOffScreenTileLoading=YES時會被調用。since 5.3.0 * @param path tile path */ - (void)cancelLoadOfTileAtPath:(MATileOverlayPath)path { [super cancelLoadOfTileAtPath:path]; } /** * 根據瓦片的x/y等級返回瓦片範圍 * * @param tx x * @param ty y * @param zoom z * @return url */ - (NSString *)titleBoundsByX:(NSInteger)tx Y:(NSInteger)ty Z:(NSInteger)zoom { double minX = [self pixels2Meters:(tx * titleSize) zoom:zoom]; double maxY = -[self pixels2Meters:(ty * titleSize) zoom:zoom]; double maxX = [self pixels2Meters:((tx + 1) * titleSize) zoom:zoom]; double minY = -[self pixels2Meters:((ty + 1) * titleSize) zoom:zoom]; //轉換成經緯度 minX = [self meters2Lon:minX]; minY = [self meters2Lat:minY]; maxX = [self meters2Lon:maxX]; maxY = [self meters2Lat:maxY]; //座標轉換工具類構造方法 Gps( WGS-84) 轉 爲高德地圖須要的座標 CLLocationCoordinate2D amapcoord = AMapCoordinateConvert(CLLocationCoordinate2DMake(minY, minX), AMapCoordinateTypeGPS); minY = amapcoord.latitude; minX = amapcoord.longitude; CLLocationCoordinate2D maxAmapcoord = AMapCoordinateConvert(CLLocationCoordinate2DMake(maxY, maxX), AMapCoordinateTypeGPS); maxY = maxAmapcoord.latitude; maxX = maxAmapcoord.longitude; NSString * result = [[NSString alloc] initWithFormat:@"%f,%f,%f,%f&width=256&height=256", minX, minY, maxX, maxY]; return result; } /** * 根據像素、等級算出座標 * * @param p p * @param zoom z * @return double */ - (double)pixels2Meters:(NSInteger)p zoom:(NSInteger)zoom { return p * [self resolution:zoom] - originShift; } /** * 計算分辨率 * * @param zoom z * @return double */ - (double)resolution:(NSInteger)zoom { return initialResolution / (pow(2, zoom)); } /** * X米轉經緯度 */ - (double)meters2Lon:(double)mx { double lon = mx * DEGREE_PER_METER; return lon; } /** * Y米轉經緯度 */ - (double)meters2Lat:(double)my { double lat = my * DEGREE_PER_METER; lat = 180.0 / M_PI * (2 * atan(exp(lat * RAD_PER_DEGREE)) - HALF_PI); return lat; } @end
其中,- (void)loadTileAtPath:(MATileOverlayPath)path result:(void (^)(NSData *tileData, NSError *error))result;
函數中,使用本身寫的 網絡訪問層去請求 wms 服務,並經過 result 函數貼到地圖上。你也能夠 改寫成本身的網絡訪問層。api
爲啥要重載 - (void)loadTileAtPath:(MATileOverlayPath)path result:(void (^)(NSData *tileData, NSError *error))result;
函數,由於只是從載 - (NSURL *)URLForTilePath:(MATileOverlayPath)path;
生成 NSURL 後,loadTileAtPath 函數會去經過網絡請求加載 wms 服務,然而,這一步網絡請求會報錯:NSURLConnection -errorcode -1004,且一個星期沒有解決爲啥報錯,因此只得重寫,若是有熟悉高德地圖 api 的小夥伴可以給予解答,不勝感激。markdown
若是使用 AFNetworking 要注意修改支持的類型:網絡
AFHTTPSessionManager * manager = [[AFHTTPSessionManager alloc] init]; AFHTTPResponseSerializer *serializer=[AFHTTPResponseSerializer serializer]; serializer.acceptableContentTypes = [NSSet setWithObject:@"image/png"]; manager.responseSerializer = serializer;