在网站或手机应用开发过程中,挑选合适的地图API极为关键,特别是在需要实现国外地图功能时,这一点尤为重要。这就像在迷宫里寻找出路,一旦选错了地图API,项目可能会遇到难题,这正是我们的痛点。
明确项目需求的关键
项目若需国外地图,需明确各项功能要求。例如,近期项目中需用到国外地图、定位和路线查询功能。不可随意挑选,就如同沙漠之旅不能仅带一件薄衣。这要求我们进行详尽调研,若需求不明确,后期功能可能不完善或无法正常使用。不同地点,用户对地图的需求各异。比如,在复杂地形的城市,路线查询的准确性就显得尤为重要。
地图API调研的重要性
在开发初期,研究各种地图API至关重要。这就像挑选市场上的商品,必须了解哪款性价比更优。在2019年9月20日之前,各种地图API各有特点。我们不能仅凭名气来判断。以百度地图为例,尽管在国内颇负盛名,但其坐标系统限制了其在国外的应用。此外,申请其海外服务权限流程繁琐,需要满足认证开发者等条件。
使用百度地图的限制
百度地图在国外项目应用中存在不少限制。比如,其坐标系统不适用,这几乎排除了在国外使用它的可能性。此外,开发者网站常常无法正常访问,需要借助VPN或翻墙,这相当麻烦。尽管它的API文档详尽,但在国外这种特殊情况下,其优势明显减弱。在国内使用时,也存在一些问题,比如执行地理定位的应用必须符合W3C标准,但定位有时并不准确,而且只接受双币卡,像国内常用的VISA卡就无法使用。
高德地图基本情况
高德地图在国内颇受欢迎。这款地图在国内使用频率较高,纳斯达克上市时其名为AMap。它主要向互联网企业和个人提供免费的API服务。同时,它还具备海外地图、定位和搜索等功能。然而,它存在一个缺陷,即未提供地图偏移转换的接口。若需将GPS坐标转换为火星坐标,用户需升级至高级用户API。这对有特殊需求的开发者来说不太方便。在实际应用中,若不进行升级,可能会影响坐标转换的精确度。
其他地图API参与调研
<!DOCTYPE html>
<html>
<head>
<title>Geolocation</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
height: 100%;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
// Note: This example requires that you consent to location sharing when
// prompted by your browser. If you see the error "The Geolocation service
// failed.", it means you probably did not give permission for the browser to
// locate you.
var map, infoWindow;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: -34.397, lng: 150.644},
zoom: 6
});
infoWindow = new google.maps.InfoWindow;
// Try HTML5 geolocation.
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
infoWindow.setPosition(pos);
infoWindow.setContent('Location found.');
infoWindow.open(map);
map.setCenter(pos);
}, function() {
handleLocationError(true, infoWindow, map.getCenter());
});
} else {
// Browser doesn't support Geolocation
handleLocationError(false, infoWindow, map.getCenter());
}
}
function handleLocationError(browserHasGeolocation, infoWindow, pos) {
infoWindow.setPosition(pos);
infoWindow.setContent(browserHasGeolocation ?
'Error: The Geolocation service failed.' :
'Error: Your browser doesn't support geolocation.');
infoWindow.open(map);
}
</script>
<script async defer
//这里是重点 -- 需要填写上面申请到的apiKey
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
</script>
</body>
</html>
本次调研考察了多款地图API,但并未详尽说明。这些API在各自的功能领域各有特色。或许有人觉得信息不够全面,但完全可以自行查阅资料,深入探究。我们的研究是在2019年9月20日之前完成的,相关API也可能有所更新,市场状况也可能有所变动。
定位相关注意事项
W3C Geolocation standard
Applications that want to perform geolocation must support the W3C Geolocation standard. Notice that the sample code above determines the user's location through the W3C navigator.geolocation property.
Some browsers use IP addresses to detect a user's location. However, it may only provide a rough estimate of a user's location. The W3C approach is the easiest and most fully-supported so it should be prioritized over other geolocation methods.
在定位方面,不同算法可能导致不同结果。例如,有些代码定位可能会出现偏差甚至无法成功。虽然官方解释称这需要遵循W3C标准,但实际操作中却涉及绑卡等复杂环节。在这种情况下,直接使用苹果自带的定位功能来获取位置并进行标记是一种可行的解决方案。同时,我们还需要根据项目中的实际测试结果来做出相应的选择。
在使用地图API时,你是否遇到过一些让人摸不着头脑的问题?欢迎您分享您的遭遇,或者给这篇文章点赞,甚至转发。
//
// ViewController.m
// googleDemo
//
// Created by 王杰 on 2019/9/18.
// Copyright © 2019 王杰. All rights reserved.
//
#import "ViewController.h"
#import <GoogleMaps/GoogleMaps.h>
#import <GooglePlaces/GooglePlaces.h>
@interface ViewController ()<CLLocationManagerDelegate>
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
@property (weak, nonatomic) IBOutlet UILabel *addressLabel;
@property (strong, nonatomic) CLLocationManager *locationManager;
@end
@implementation ViewController{
GMSPlacesClient *_placesClient;
GMSCameraPosition *camera;
GMSMapView *mapView;
GMSMarker *marker;
}
-(CLLocationManager *)locationManager{
if (!_locationManager) {
_locationManager = [[CLLocationManager alloc] init];
_locationManager.desiredAccuracy=kCLLocationAccuracyBest;
_locationManager.distanceFilter=200;
_locationManager.delegate = self;
}
return _locationManager;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
if (CLLocationManager.authorizationStatus == kCLAuthorizationStatusNotDetermined) {
[self.locationManager requestWhenInUseAuthorization];
// [self.locationManager requestAlwaysAuthorization];
}
[self.locationManager startUpdatingLocation];//开启定位
CLLocationCoordinate2D coor = self.locationManager.location.coordinate;
marker.position = CLLocationCoordinate2DMake(coor.latitude,coor.longitude);
_placesClient = [GMSPlacesClient sharedClient];
// [self.locationManager requestAlwaysAuthorization];
// GMSPlaceField fields = (GMSPlaceFieldName | GMSPlaceFieldPlaceID);
// [_placesClient findPlaceLikelihoodsFromCurrentLocationWithPlaceFields:fields callback:^(NSArray * _Nullable likelihoods, NSError * _Nullable error) {
// if (error != nil) {
// NSLog(@"An error occurred %@", [error localizedDescription]);
// return;
// }
// if (likelihoods != nil) {
// for (GMSPlaceLikelihood *likelihood in likelihoods) {
// GMSPlace *place = likelihood.place;
// NSLog(@"Current place name: %@", place.name);
// NSLog(@"Place ID: %@", place.placeID);
// }
// }
// }];
camera = [GMSCameraPosition cameraWithLatitude:coor.latitude
longitude:coor.longitude
zoom:5];
mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
mapView.myLocationEnabled = YES;
mapView.frame = CGRectMake(0, 0,[UIScreen mainScreen].bounds.size.width, 500);
[self.view addSubview:mapView];
[self.view sendSubviewToBack:mapView];
// Creates a marker in the center of the map.
marker = [[GMSMarker alloc] init];
marker.position = coor;
marker.title = @"当前位置";
marker.snippet = @"Australia";
marker.map = mapView;
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
CLLocationCoordinate2D coor = manager.location.coordinate;
coor = CLLocationCoordinate2DMake(15.898372, 101.604046);
marker.position = coor;
camera = [GMSCameraPosition cameraWithLatitude:coor.latitude
longitude:coor.longitude
zoom:camera.zoom];
mapView.camera = camera;
}
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{
NSLog(@"456");
}
- (IBAction)getCurrentPlace:(UIButton *)sender {
if (CLLocationManager.authorizationStatus == kCLAuthorizationStatusNotDetermined) {
[self.locationManager requestWhenInUseAuthorization];
// [self.locationManager requestAlwaysAuthorization];
}
[_placesClient currentPlaceWithCallback:^(GMSPlaceLikelihoodList * _Nullable likelihoodList, NSError * _Nullable error) {
if (error != nil) {
NSLog(@"Current Place error %@", [error localizedDescription]);
return;
}
self.nameLabel.text = @"No current place";
self.addressLabel.text = @"";
if (likelihoodList != nil) {
GMSPlace *place = [[[likelihoodList likelihoods] firstObject] place];
if (place != nil) {
self.nameLabel.text = place.name;
self.addressLabel.text = [[place.formattedAddress componentsSeparatedByString:@", "]
componentsJoinedByString:@"n"];
}
}
}];
}
@end