如何使用适用于 iOS 的谷歌地图 sdk 设置区域?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15040409/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to setRegion with google maps sdk for iOS?
提问by Mecid
How to setRegion with google maps sdk for iOS? I want set zoom for location and radius of markers.
如何使用适用于 iOS 的谷歌地图 sdk 设置区域?我想为标记的位置和半径设置缩放。
回答by Saxon Druce
UPDATE:
更新:
The original answer below is obsolete as of version 1.2 of the SDK - you can now use the fitBounds:
method of the GMSCameraUpdate
class:
下面的原始答案自 SDK 1.2 版起已过时 - 您现在可以使用该类的fitBounds:
方法GMSCameraUpdate
:
https://developers.google.com/maps/documentation/ios/reference/interface_g_m_s_camera_update
https://developers.google.com/maps/documentation/ios/reference/interface_g_m_s_camera_update
Original answer:
原答案:
The MKMapPoint
type in MapKit defines a 2D projection of a map. Although the actual values of the projection are meant to be opaque, they turn out to be equivalent to pixels at zoom level 20. This can be used to convert lat/lon values to pixels, and therefore a scale, and therefore a zoom level.
MKMapPoint
MapKit 中的类型定义了地图的 2D 投影。虽然投影的实际值是不透明的,但结果证明它们等效于缩放级别 20 的像素。这可用于将纬度/经度值转换为像素,因此是比例,因此是缩放级别。
Start by defining two locations which specify the bounds of the region you want to display. These could be opposite corners of the bounding box, or just two locations, for example:
首先定义两个位置,它们指定要显示的区域的边界。这些可能是边界框的对角,或者只是两个位置,例如:
CLLocationCoordinate2D location1 =
CLLocationCoordinate2DMake(-33.8683, 151.2086); // Sydney
CLLocationCoordinate2D location2 =
CLLocationCoordinate2DMake(-31.9554, 115.8585); // Perth
If you have more than two points that you want to include, you could calculate the bounds of them yourself. This can also be done using GMSCoordinateBounds
, for example:
如果您想要包含两个以上的点,您可以自己计算它们的边界。这也可以使用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;
Next, you need to get the size of the map view in points. You could use this:
接下来,您需要以点为单位获取地图视图的大小。你可以用这个:
float mapViewWidth = _mapView.frame.size.width;
float mapViewHeight = _mapView.frame.size.height;
But that will only work if you've already created the map view. Also, if you're using the sample code in the getting started guide, the frame is set to CGRectZero
, as the actual size will be set later to fill the screen. In these cases if you're creating a full-screen map then you might want something like this:
但这只有在您已经创建了地图视图时才有效。此外,如果您使用入门指南中的示例代码,则框架设置为CGRectZero
,因为稍后将设置实际大小以填充屏幕。在这些情况下,如果您正在创建全屏地图,那么您可能需要这样的东西:
float mapViewWidth = [UIScreen mainScreen].applicationFrame.size.width;
float mapViewHeight = [UIScreen mainScreen].applicationFrame.size.height;
Otherwise, use the size which you're creating your map view with.
否则,请使用您用于创建地图视图的大小。
Now you have the info necessary to calculate the camera position:
现在您有了计算相机位置所需的信息:
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];
You can then initialize the map view with this camera, or set the map view to this camera.
然后,您可以使用此相机初始化地图视图,或将地图视图设置为此相机。
For this code to compile, you will need to add the MapKit framework to your project, and then also import it:
要编译此代码,您需要将 MapKit 框架添加到您的项目中,然后导入它:
#import <MapKit/MapKit.h>
Note that this code doesn't handle wrap-around if your coordinates span across the date line. For example if you tried using this code with Tokyo and Hawaii, instead of displaying an area of the Pacific, it will try to display almost the entire world. In portrait mode it's not possible to zoom out far enough to see Hawaii on the left and Tokyo on the right, and so the map ends up centred on Africa with neither location visible. You could modify the above code to handle the wrap-around at the date line if you wanted to.
请注意,如果您的坐标跨越日期变更线,则此代码不会处理环绕。例如,如果您尝试在东京和夏威夷使用此代码,而不是显示太平洋的某个区域,它将尝试显示几乎整个世界。在纵向模式下,不可能缩小到足以看到左侧的夏威夷和右侧的东京,因此地图最终以非洲为中心,两个位置都不可见。如果你愿意,你可以修改上面的代码来处理日期变更线的环绕。
回答by Evgeny Tanhilevich
UPDATE
更新
All issues were fixed in the latest version of Google maps (1.5). Standard method [mapView_ animateWithCameraUpdate:[GMSCameraUpdate fitBounds:bounds]];
can noow be used instead of the code below
所有问题都在最新版本的谷歌地图 (1.5) 中得到修复。[mapView_ animateWithCameraUpdate:[GMSCameraUpdate fitBounds:bounds]];
现在可以使用标准方法代替下面的代码
ORIGINAL ANSWER
原答案
[GMSCameraUpdate fitBounds]
does not give accurate results in my version of the SDK (1.2.0). I am using the code below instead of it. The formulae are taken from the Mercator Projection. The world is latitudonally bounded at 85 degrees as per Google Documentation.
[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];
}
回答by fellowworldcitizen
Saxun Druce's answer is really good. But in addition, if you want to calculate a radius from any location you can do that with the following code:
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];
回答by Suraj K Thomas
If you have latitude and longitude of 'far-left' and 'near-right' corners of the google map ,you can display the data in swift using below code
如果您有谷歌地图的“远左”和“近右”角的纬度和经度,您可以使用以下代码快速显示数据
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;
Thislink may also be helpful for related things.
此链接也可能对相关内容有所帮助。
回答by Stefan Fisk
I currently using this method.
我目前使用这种方法。
self.markers is a dictionary with markers stored by a location ID, self.currentLocation is a CLLocation2D, and self.mapView is a GMSMapView.
self.markers 是一个字典,带有由位置 ID 存储的标记,self.currentLocation 是一个 CLLocation2D,而 self.mapView 是一个 GMSMapView。
The maths here is a check on whether to match the sizes on the width or the height, and then a calculation of the zoom based on the fact that x1 / pow(2, zoom1) = x2 / pow(2, zoom2)", leading to zoom2 = log2(x2 * pow(2, self.mapView.camera.zoom) / x1).
这里的数学是检查是否匹配宽度或高度的大小,然后根据 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];
}
回答by adijazz91
As per new release of GoogleMaps iOS sdk 1.9.2, We can set up using Camera's position, zoom level, viewingAngle.
根据新发布的GoogleMaps iOS sdk 1.9.2,我们可以使用Camera 的位置、缩放级别、viewingAngle 进行设置。
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];
For Further reference see this PDF document.
如需进一步参考,请参阅此 PDF 文档。
you can also set minimum and maximum Zoom level as per your need:
您还可以根据需要设置最小和最大缩放级别:
[self.mapView setMinZoom:10 maxZoom:30];
Hope this solves the problem.
希望这能解决问题。
回答by friedbunny
As of June 2014, this answeris the simplest way to iterate over a given array of markers and then set bounds accordingly.
截至 2014 年 6 月,此答案是迭代给定标记数组然后相应地设置边界的最简单方法。
回答by Bohrnsen
I searched through the header files of the framework and only found the interface that could be used for the following code which could be a start. The problem here is that i can not find any imports of GMSCoordinateBounds in one of the other headers so i can not find a way to display this region in GMSMapView.
我搜索了框架的头文件,只找到了可以用于以下代码的接口,可以作为一个开始。这里的问题是我在其他标题之一中找不到 GMSCoordinateBounds 的任何导入,因此我找不到在 GMSMapView 中显示该区域的方法。
GMSVisibleRegion region;
region.farLeft = CLLocationCoordinate2DMake(farLeftLatitude, farLeftlongitude);
region.farRight = CLLocationCoordinate2DMake(farRightlatitude, farRightlongitude);
GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithRegion:region];
回答by iOS Developer
// I have found this method that worked for me
// 我发现这个方法对我有用
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;
}