如何使用适用于 iOS 的 google maps sdk 设置区域?我想为标记的位置和半径设置缩放。
9 回答
更新:
从 SDK 1.2 版开始,下面的原始答案已过时 - 您现在可以使用该类的fitBounds:
方法GMSCameraUpdate
:
https://developers.google.com/maps/documentation/ios/reference/interface_g_m_s_camera_update
原答案:
MapKit 中的MKMapPoint
类型定义了地图的 2D 投影。尽管投影的实际值是不透明的,但它们最终等同于缩放级别 20 的像素。这可用于将纬度/经度值转换为像素,从而转换为比例,从而转换为缩放级别。
首先定义两个位置,指定要显示的区域的边界。这些可能是边界框的对角,或者只是两个位置,例如:
CLLocationCoordinate2D location1 =
CLLocationCoordinate2DMake(-33.8683, 151.2086); // Sydney
CLLocationCoordinate2D location2 =
CLLocationCoordinate2DMake(-31.9554, 115.8585); // Perth
如果您要包含两个以上的点,您可以自己计算它们的界限。这也可以使用 来完成GMSCoordinateBounds
,例如:
GMSCoordinateBounds* bounds =
[[GMSCoordinateBounds alloc]
initWithCoordinate: CLLocationCoordinate2DMake(-33.8683, 151.2086) // Sydney
andCoordinate: CLLocationCoordinate2DMake(-31.9554, 115.8585)]; // Perth
bounds = [bounds including:
CLLocationCoordinate2DMake(-12.4667, 130.8333)]; // Darwin
CLLocationCoordinate2D location1 = bounds.southWest;
CLLocationCoordinate2D location2 = bounds.northEast;
接下来,您需要以点为单位获取地图视图的大小。你可以使用这个:
float mapViewWidth = _mapView.frame.size.width;
float mapViewHeight = _mapView.frame.size.height;
但这只有在您已经创建了地图视图时才有效。此外,如果您使用入门指南中的示例代码,则框架设置为CGRectZero
,因为稍后将设置实际大小以填充屏幕。在这些情况下,如果您正在创建全屏地图,那么您可能需要这样的东西:
float mapViewWidth = [UIScreen mainScreen].applicationFrame.size.width;
float mapViewHeight = [UIScreen mainScreen].applicationFrame.size.height;
否则,请使用您创建地图视图的大小。
现在您有了计算相机位置所需的信息:
MKMapPoint point1 = MKMapPointForCoordinate(location1);
MKMapPoint point2 = MKMapPointForCoordinate(location2);
MKMapPoint centrePoint = MKMapPointMake(
(point1.x + point2.x) / 2,
(point1.y + point2.y) / 2);
CLLocationCoordinate2D centreLocation = MKCoordinateForMapPoint(centrePoint);
double mapScaleWidth = mapViewWidth / fabs(point2.x - point1.x);
double mapScaleHeight = mapViewHeight / fabs(point2.y - point1.y);
double mapScale = MIN(mapScaleWidth, mapScaleHeight);
double zoomLevel = 20 + log2(mapScale);
GMSCameraPosition *camera = [GMSCameraPosition
cameraWithLatitude: centreLocation.latitude
longitude: centreLocation.longitude
zoom: zoomLevel];
然后,您可以使用此相机初始化地图视图,或将地图视图设置为此相机。
要编译此代码,您需要将 MapKit 框架添加到您的项目中,然后将其导入:
#import <MapKit/MapKit.h>
请注意,如果您的坐标跨越日期线,则此代码不会处理环绕。例如,如果您尝试将此代码用于东京和夏威夷,而不是显示太平洋地区,它将尝试显示几乎整个世界。在纵向模式下,无法缩小到足以看到左侧的夏威夷和右侧的东京,因此地图最终以非洲为中心,两个位置都不可见。如果您愿意,可以修改上述代码以处理日期行处的环绕。
更新
所有问题都在最新版本的 Google 地图 (1.5) 中得到修复。[mapView_ animateWithCameraUpdate:[GMSCameraUpdate fitBounds:bounds]];
现在可以使用标准方法代替下面的代码
原始答案
[GMSCameraUpdate fitBounds]
在我的 SDK (1.2.0) 版本中没有给出准确的结果。我正在使用下面的代码而不是它。公式取自墨卡托投影。根据Google 文档,世界的纬度为 85 度。
#import <stdlib.h>
-(void) animateBoundsNorth:(CGFloat)north West:(CGFloat)west South:(CGFloat)south East:(CGFloat)east Padding:(int)padding {
CGFloat northRad = north * M_PI / 180.0;
CGFloat northProj = logf(tanf(M_PI_4 + northRad/2.0));
CGFloat southRad = south * M_PI / 180.0;
CGFloat southProj = logf(tanf(M_PI_4 + southRad/2.0));
CGFloat topRad = 85.0 * M_PI / 180.0;
CGFloat topProj = logf(tanf(M_PI_4 + topRad/2.0));
CGFloat zoomLat = log2f((mapView_.bounds.size.height - padding * 2) * 2 * topProj /(northProj - southProj)) - 8;
CGFloat zoomLon = log2f((mapView_.bounds.size.width - padding * 2) * 360/(east - west)) - 8;
GMSCameraUpdate *update = [GMSCameraUpdate setTarget:CLLocationCoordinate2DMake((north+south)/2.0, (west+east)/2.0) zoom:MIN(zoomLat, zoomLon)];
[mapView_ animateWithCameraUpdate:update];
}
Saxun Druce 的回答非常好。但此外,如果您想从任何位置计算半径,您可以使用以下代码来执行此操作:
CLLocationCoordinate2D center = CLLocationCoordinate2DMake([currentLocationLat doubleValue],[currentLocationLong doubleValue]);
float radius = 25*1000; //radius in meters (25km)
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(center, radius*2, radius*2);
CLLocationCoordinate2D northEast = CLLocationCoordinate2DMake(region.center.latitude - region.span.latitudeDelta/2, region.center.longitude - region.span.longitudeDelta/2);
CLLocationCoordinate2D southWest = CLLocationCoordinate2DMake(region.center.latitude + region.span.latitudeDelta/2, region.center.longitude + region.span.longitudeDelta/2);
GMSCoordinateBounds* bounds = [[GMSCoordinateBounds alloc]
initWithCoordinate: northEast
andCoordinate: southWest];
如果您有谷歌地图的“最左”和“近右”角的纬度和经度,您可以使用以下代码快速显示数据
var region:GMSVisibleRegion = GMSVisibleRegion()
region.nearLeft = CLLocationCoordinate2DMake(nearleflat, nearleftlong)
region.farRight = CLLocationCoordinate2DMake(fareastlat,fareastlong)
let bounds = GMSCoordinateBounds(coordinate: region.nearLeft,coordinate: region.farRight)
let camera = googleMapView.cameraForBounds(bounds, insets:UIEdgeInsetsZero)
googleMapView.camera = camera;
此链接也可能对相关内容有所帮助。
我目前使用这种方法。
self.markers 是一个字典,其标记由位置 ID 存储,self.currentLocation 是一个 CLLocation2D,self.mapView 是一个 GMSMapView。
这里的数学是检查是否匹配宽度或高度的大小,然后根据 x1 / pow(2, zoom1) = x2 / pow(2, zoom2)"的事实计算缩放比例,导致 zoom2 = log2(x2 * pow(2, self.mapView.camera.zoom) / x1)。
- (void)fitMarkers
{
if (2 > self.markers.count)
{
[self.mapView animateToCameraPosition:[GMSCameraPosition cameraWithTarget:self.currentLocation.coordinate zoom:kZoom]];
return;
}
NSArray* markers = self.markers.allValues;
GMSCoordinateBounds* markerBounds = [[GMSCoordinateBounds alloc] initWithCoordinate:((id<GMSMarker>)markers[0]).position andCoordinate:((id<GMSMarker>)markers[1]).position];
for (id<GMSMarker> marker in markers)
{
markerBounds = [markerBounds including:marker.position];
}
// get marker bounds in points
CGPoint markerBoundsTopLeft = [self.mapView.projection pointForCoordinate:CLLocationCoordinate2DMake(markerBounds.northEast.latitude, markerBounds.southWest.longitude)];
CGPoint markerBoundsBottomRight = [self.mapView.projection pointForCoordinate:CLLocationCoordinate2DMake(markerBounds.southWest.latitude, markerBounds.northEast.longitude)];
// get user location in points
CGPoint currentLocation = [self.mapView.projection pointForCoordinate:self.currentLocation.coordinate];
CGPoint markerBoundsCurrentLocationMaxDelta = CGPointMake(MAX(fabs(currentLocation.x - markerBoundsTopLeft.x), fabs(currentLocation.x - markerBoundsBottomRight.x)), MAX(fabs(currentLocation.y - markerBoundsTopLeft.y), fabs(currentLocation.y - markerBoundsBottomRight.y)));
// the marker bounds centered on self.currentLocation
CGSize centeredMarkerBoundsSize = CGSizeMake(2.0 * markerBoundsCurrentLocationMaxDelta.x, 2.0 * markerBoundsCurrentLocationMaxDelta.y);
// inset the view bounds to fit markers
CGSize insetViewBoundsSize = CGSizeMake(self.mapView.bounds.size.width - kMarkerSize / 2.0 - kMarkerMargin, self.mapView.bounds.size.height - kMarkerSize / 2.0 - kMarkerSize);
CGFloat x1;
CGFloat x2;
// decide which axis to calculate the zoom level with by comparing the width/height ratios
if (centeredMarkerBoundsSize.width / centeredMarkerBoundsSize.height > insetViewBoundsSize.width / insetViewBoundsSize.height)
{
x1 = centeredMarkerBoundsSize.width;
x2 = insetViewBoundsSize.width;
}
else
{
x1 = centeredMarkerBoundsSize.height;
x2 = insetViewBoundsSize.height;
}
CGFloat zoom = log2(x2 * pow(2, self.mapView.camera.zoom) / x1);
GMSCameraPosition* camera = [GMSCameraPosition cameraWithTarget:self.currentLocation.coordinate zoom:zoom];
[self.mapView animateToCameraPosition:camera];
}
根据 GoogleMaps iOS sdk 1.9.2 的新版本,我们可以使用相机的位置、缩放级别、查看角度进行设置。
GMSCameraPosition* camera = [GMSCameraPosition cameraWithLatitude:28.6100
longitude:77.2300
zoom:14.0
bearing:0
viewingAngle:0.00];
self.mapView = [GMSMapView mapWithFrame:CGRectMake(0, 45, self.view.frame.size.width, self.view.frame.size.height - 45) camera:camera];
mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
mapView.delegate = self;
mapView.myLocationEnabled = YES;
mapView.mapType = kGMSTypeTerrain;
mapView.settings.compassButton = YES;
mapView.settings.myLocationButton = YES;
[self.mapView setMinZoom:10 maxZoom:18];
GMSMarker* marker = [[GMSMarker alloc] init];
marker.position = CLLocationCoordinate2DMake(28.6100, 77.2300);
marker.title = @"New Delhi";
marker.snippet = @"Capital Of India";
marker.map = self.mapView;
marker.appearAnimation = kGMSMarkerAnimationPop;
marker.icon = [GMSMarker markerImageWithColor:[UIColor grayColor]];
[self.view addSubview:self.mapView];
如需进一步参考,请参阅此 PDF 文档。
您还可以根据需要设置最小和最大缩放级别:
[self.mapView setMinZoom:10 maxZoom:30];
希望这能解决问题。
截至 2014 年 6 月,此答案是迭代给定标记数组并相应设置边界的最简单方法。
我搜索了框架的头文件,只找到了可以用于以下代码的接口,这可能是一个开始。这里的问题是我在其他标题之一中找不到 GMSCoordinateBounds 的任何导入,因此我找不到在 GMSMapView 中显示该区域的方法。
GMSVisibleRegion region;
region.farLeft = CLLocationCoordinate2DMake(farLeftLatitude, farLeftlongitude);
region.farRight = CLLocationCoordinate2DMake(farRightlatitude, farRightlongitude);
GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithRegion:region];
// 我发现这个方法对我有用
func setMapZoomToRadius(lat:Double, lng:Double, var mile:Double)
{
let center = CLLocationCoordinate2DMake(lat, lng)
let radius: Double = (mile ) * 621.371
let region = MKCoordinateRegionMakeWithDistance(center, radius * 2.0, radius * 2.0)
let northEast = CLLocationCoordinate2DMake(region.center.latitude - region.span.latitudeDelta, region.center.longitude - region.span.longitudeDelta)
let southWest = CLLocationCoordinate2DMake(region.center.latitude + region.span.latitudeDelta, region.center.longitude + region.span.longitudeDelta)
print("\(region.center.longitude) \(region.span.longitudeDelta)")
let bounds = GMSCoordinateBounds(coordinate: southWest, coordinate: northEast)
let camera = googleMapView.cameraForBounds(bounds, insets:UIEdgeInsetsZero)
googleMapView.camera = camera;
}