ios 缩放 MKMapView 以适合注释引脚?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4680649/
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
Zooming MKMapView to fit annotation pins?
提问by fuzzygoat
I am using MKMapView and have added a number of annotation pins to the map about a 5-10 kilometre area. When I run the application my map starts zoomed out to show the whole world, what is the best way to zoom the map so the pins fit the view?
我正在使用 MKMapView 并在大约 5-10 公里区域的地图上添加了许多注释图钉。当我运行应用程序时,我的地图开始缩小以显示整个世界,缩放地图以使图钉适合视图的最佳方法是什么?
EDIT:My initial thinking would be to use MKCoordinateRegionMake and calculate the coordinate centre, longitudeDelta and latitudeDelta from my annotations. I am pretty sure this will work, but I just wanted to check I was not missing anything obvious.
编辑:我最初的想法是使用 MKCoordinateRegionMake 并根据我的注释计算坐标中心、longitudeDelta 和 latitudeDelta。我很确定这会起作用,但我只是想检查一下我没有遗漏任何明显的东西。
Code added, BTW: FGLocation is an class that conforms to MKAnnotation
, locationFake is an NSMutableArray
of these objects. Comments are always welcome ....
添加代码,顺便说一句:FGLocation 是一个符合 的类MKAnnotation
,locationFake 是NSMutableArray
这些对象中的一个。随时欢迎评论......
- (MKCoordinateRegion)regionFromLocations {
CLLocationCoordinate2D upper = [[locationFake objectAtIndex:0] coordinate];
CLLocationCoordinate2D lower = [[locationFake objectAtIndex:0] coordinate];
// FIND LIMITS
for(FGLocation *eachLocation in locationFake) {
if([eachLocation coordinate].latitude > upper.latitude) upper.latitude = [eachLocation coordinate].latitude;
if([eachLocation coordinate].latitude < lower.latitude) lower.latitude = [eachLocation coordinate].latitude;
if([eachLocation coordinate].longitude > upper.longitude) upper.longitude = [eachLocation coordinate].longitude;
if([eachLocation coordinate].longitude < lower.longitude) lower.longitude = [eachLocation coordinate].longitude;
}
// FIND REGION
MKCoordinateSpan locationSpan;
locationSpan.latitudeDelta = upper.latitude - lower.latitude;
locationSpan.longitudeDelta = upper.longitude - lower.longitude;
CLLocationCoordinate2D locationCenter;
locationCenter.latitude = (upper.latitude + lower.latitude) / 2;
locationCenter.longitude = (upper.longitude + lower.longitude) / 2;
MKCoordinateRegion region = MKCoordinateRegionMake(locationCenter, locationSpan);
return region;
}
采纳答案by Matthew Frederick
You've got it right.
你说得对。
Find your maximum and minimum latitudes and longitudes, apply some simple arithmetic, and use MKCoordinateRegionMake
.
找到您的最大和最小纬度和经度,应用一些简单的算术,然后使用MKCoordinateRegionMake
.
For iOS 7 and above, use showAnnotations:animated:
, from MKMapView.h
:
对于 iOS 7 及更高版本,请使用showAnnotations:animated:
, from MKMapView.h
:
// Position the map such that the provided array of annotations are all visible to the fullest extent possible.
- (void)showAnnotations:(NSArray *)annotations animated:(BOOL)animated NS_AVAILABLE(10_9, 7_0);
回答by jowie
This is the one I found herethat worked for me:
这是我在这里找到的对我有用的:
(EDIT: I have updated the solution using @Micah's suggestion to increase the pointRect by 0.1 to ensure the rect doesn't end up being infinitesimally small!)
(编辑:我已经使用@Micah 的建议更新了解决方案,将 pointRect 增加 0.1,以确保 rect 最终不会变得非常小!)
MKMapRect zoomRect = MKMapRectNull;
for (id <MKAnnotation> annotation in mapView.annotations)
{
MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
MKMapRect pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);
zoomRect = MKMapRectUnion(zoomRect, pointRect);
}
[mapView setVisibleMapRect:zoomRect animated:YES];
You could also update this to include the userLocation pin by replacing the first line with:
您还可以通过将第一行替换为以下内容来更新它以包含 userLocation 引脚:
MKMapPoint annotationPoint = MKMapPointForCoordinate(mapView.userLocation.coordinate);
MKMapRect zoomRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);
回答by Ryan Berg
Apple has added a new method for IOS 7 to simplify life a bit.
苹果为 IOS 7 添加了一种新方法,以稍微简化生活。
[mapView showAnnotations:yourAnnotationArray animated:YES];
You can easily pull from an array stored in the map view:
您可以轻松地从存储在地图视图中的数组中提取:
yourAnnotationArray = mapView.annotations;
and quickly adjust the camera too!
并快速调整相机!
mapView.camera.altitude *= 1.4;
this won't work unless the user has iOS 7+ or OS X 10.9+ installed. check out custom animation here
除非用户安装了 iOS 7+ 或 OS X 10.9+,否则这将不起作用。在此处查看自定义动画
回答by Rafael Moreira
I use this this code and works fine for me:
我使用此代码并为我工作正常:
-(void)zoomToFitMapAnnotations:(MKMapView*)aMapView
{
if([aMapView.annotations count] == 0)
return;
CLLocationCoordinate2D topLeftCoord;
topLeftCoord.latitude = -90;
topLeftCoord.longitude = 180;
CLLocationCoordinate2D bottomRightCoord;
bottomRightCoord.latitude = 90;
bottomRightCoord.longitude = -180;
for(MapViewAnnotation *annotation in mapView.annotations)
{
topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude);
topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude);
bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude);
bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude);
}
MKCoordinateRegion region;
region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5;
region.center.longitude = topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5;
region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.1; // Add a little extra space on the sides
region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.1; // Add a little extra space on the sides
region = [aMapView regionThatFits:region];
[mapView setRegion:region animated:YES];
}
回答by Sreedeepkesav M S
In Swift use
在 Swift 中使用
mapView.showAnnotations(annotationArray, animated: true)
In Objective c
在目标 c
[mapView showAnnotations:annotationArray animated:YES];
回答by oscar castellon
Swift 3 This is de correct way for fit all annotations in map.
Swift 3 这是适合地图中所有注释的正确方法。
func zoomMapaFitAnnotations() {
var zoomRect = MKMapRectNull
for annotation in mapview.annotations {
let annotationPoint = MKMapPointForCoordinate(annotation.coordinate)
let pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0, 0)
if (MKMapRectIsNull(zoomRect)) {
zoomRect = pointRect
} else {
zoomRect = MKMapRectUnion(zoomRect, pointRect)
}
}
self.mapview.setVisibleMapRect(zoomRect, edgePadding: UIEdgeInsetsMake(50, 50, 50, 50), animated: true)
}
回答by Prashant Khanal
I have converted the answer by Rafael Moreira. The credit goes to him. For those of you looking for the Swift version, here is the code:
我已经转换了 Rafael Moreira 的答案。功劳归于他。对于那些正在寻找 Swift 版本的人,这里是代码:
func zoomToFitMapAnnotations(aMapView: MKMapView) {
guard aMapView.annotations.count > 0 else {
return
}
var topLeftCoord: CLLocationCoordinate2D = CLLocationCoordinate2D()
topLeftCoord.latitude = -90
topLeftCoord.longitude = 180
var bottomRightCoord: CLLocationCoordinate2D = CLLocationCoordinate2D()
bottomRightCoord.latitude = 90
bottomRightCoord.longitude = -180
for annotation: MKAnnotation in myMap.annotations as! [MKAnnotation]{
topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude)
topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude)
bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude)
bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude)
}
var region: MKCoordinateRegion = MKCoordinateRegion()
region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5
region.center.longitude = topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5
region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.4
region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.4
region = aMapView.regionThatFits(region)
myMap.setRegion(region, animated: true)
}
回答by Micah
@jowie's solution works great. One catch, if a map has only one annotation you'll end up with a fully zoomed out map. I added 0.1 to the rect make size to make sure setVisibleMapRect has something to zoom to.
@jowie 的解决方案效果很好。一个问题,如果地图只有一个注释,您最终会得到一张完全缩小的地图。我将 0.1 添加到 rect make size 以确保 setVisibleMapRect 可以缩放到某些内容。
MKMapRect pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);
回答by Henrik Perrochon
If your are looking for iOS 8 and above, the simplest way to do it is to set the var layoutMargins: UIEdgeInsets { get set }
of your map view before calling func showAnnotations(annotations: [MKAnnotation], animated: Bool)
如果您正在寻找iOS 8 及更高版本,最简单的方法是var layoutMargins: UIEdgeInsets { get set }
在调用之前设置地图视图的func showAnnotations(annotations: [MKAnnotation], animated: Bool)
For instance (Swift 2.1):
例如(Swift 2.1):
@IBOutlet weak var map: MKMapView! {
didSet {
map.delegate = self
map.mapType = .Standard
map.pitchEnabled = false
map.rotateEnabled = false
map.scrollEnabled = true
map.zoomEnabled = true
}
}
// call 'updateView()' when viewWillAppear or whenever you set the map annotations
func updateView() {
map.layoutMargins = UIEdgeInsets(top: 25, left: 25, bottom: 25, right: 25)
map.showAnnotations(map.annotations, animated: true)
}
回答by Ankit Srivastava
I created an extension to show all the annotations using some code from here and there in swift. This will not show all annotations if they can't be shown even at maximum zoom level.
我创建了一个扩展来使用一些代码快速显示所有注释。如果即使在最大缩放级别也无法显示所有注释,则不会显示所有注释。
import MapKit
extension MKMapView {
func fitAllAnnotations() {
var zoomRect = MKMapRectNull;
for annotation in annotations {
let annotationPoint = MKMapPointForCoordinate(annotation.coordinate)
let pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);
zoomRect = MKMapRectUnion(zoomRect, pointRect);
}
setVisibleMapRect(zoomRect, edgePadding: UIEdgeInsets(top: 50, left: 50, bottom: 50, right: 50), animated: true)
}
}