缩放 MKMapView 以适应注释图钉?
我正在使用 MKMapView 并在大约 5-10 公里区域的地图上添加了一些注释图钉。当我运行应用程序时,我的地图开始缩小以显示整个世界,缩放地图以使图钉适合视图的最佳方法是什么?
编辑: 我最初的想法是使用 MKCooperativeRegionMake 并根据我的注释计算坐标中心、longitudeDelta 和 latitudeDelta。我很确定这会起作用,但我只是想检查一下我没有遗漏任何明显的东西。
添加代码,顺便说一句: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;
}
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?
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.
Code added, BTW: FGLocation is an class that conforms to MKAnnotation
, locationFake is an NSMutableArray
of these objects. Comments are always welcome ....
- (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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(27)
你说得对。
找到最大和最小纬度和经度,应用一些简单的算术,然后使用
MKCooperativeRegionMake
。对于 iOS 7 及更高版本,请使用
showAnnotations:animated:
,来自MKMapView.h
:You've got it right.
Find your maximum and minimum latitudes and longitudes, apply some simple arithmetic, and use
MKCoordinateRegionMake
.For iOS 7 and above, use
showAnnotations:animated:
, fromMKMapView.h
:Apple 为 IOS 7 添加了一种新方法来简化生活。
您可以轻松地从地图视图中存储的数组中提取数据:
并快速调整相机!
除非用户安装了 iOS 7+ 或 OS X 10.9+,否则此功能不起作用。 此处查看自定义动画
Apple has added a new method for IOS 7 to simplify life a bit.
You can easily pull from an array stored in the map view:
and quickly adjust the camera too!
this won't work unless the user has iOS 7+ or OS X 10.9+ installed. check out custom animation here
我使用这个代码并且对我来说效果很好:
I use this this code and works fine for me:
在 Swift 中使用
在 Objective c 中
In Swift use
In Objective c
我已经转换了拉斐尔·莫雷拉的答案。功劳归于他。
对于那些正在寻找 Swift 版本的人,这里是代码:
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:
我创建了一个扩展来使用 swift 中的一些代码来显示所有注释。如果即使在最大缩放级别也无法显示所有注释,则这不会显示所有注释。
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.
Swift 3 这是适合地图中所有注释的正确方法。
Swift 3 This is de correct way for fit all annotations in map.
@jowie 的解决方案效果很好。需要注意的是,如果地图只有一个注释,您最终会得到一张完全缩小的地图。我在 rect make size 中添加了 0.1,以确保 setVisibleMapRect 有可缩放的内容。
@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.
如果您正在寻找 iOS 8 及更高版本,最简单的方法是在调用
之前设置地图视图的
varlayoutMargins: UIEdgeInsets { get set }
>func showAnnotations(annotations: [MKAnnotation],animated: Bool)例如(Swift 2.1):
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 callingfunc showAnnotations(annotations: [MKAnnotation], animated: Bool)
For instance (Swift 2.1):
在 for 循环中添加了此 If 循环,以从该方法中排除用户位置引脚(在我的情况下需要,也许在其他情况下也需要)
Added this If loop within the for loop to exclude the users location pin from this method (required in my case, and maybe others)
对于 iOS 7 及更高版本(参考 MKMapView.h):
来自 – Abhishek Bedi 的评论
您只需调用:
For iOS 7 and above (Referring MKMapView.h) :
remark from – Abhishek Bedi
You just call:
// 为 swift 5 编辑
// Edited for swift 5
用斯威夫特
In Swift
感谢 jowie,我已经将我的旧类别更新为更优雅的解决方案。分享完整的、几乎复制粘贴的解决方案
MKMapView+AnnotationsRegion.h
MKMapView+AnnotationsRegion.m
希望它能帮助别人,再次感谢 jowie!
Thanks to jowie I've updated my old category to more elegant solution. Sharing complete, almost copy&paste ready solution
MKMapView+AnnotationsRegion.h
MKMapView+AnnotationsRegion.m
Hope it helps someone and thanks again jowie!
正如 Abhishek Bedi 在评论中指出的那样,对于 iOS7 转发,执行此操作的最佳方法是:
对于我的个人项目(iOS7 之前的版本),我只是在 MKMapView 类上添加了一个类别,以封装非常常见的“可见区域”功能。操作:将其设置为能够查看 MKMapView 实例上当前加载的所有注释(这包括您可能放置的尽可能多的图钉,以及用户的位置)。结果是这样的:
.h 文件
.m 文件
如您所见,到目前为止我添加了 2 种方法:一种用于将地图的可见区域设置为适合 MKMapView 实例上当前加载的所有注释的区域,以及另一种将其设置为任何对象数组的方法。
因此,要设置 mapView 的可见区域,代码将非常简单:
我希望它有帮助 =)
As Abhishek Bedi points out in a comment, For iOS7 forward the best way to do this is:
For my personal project (prior to iOS7) I simply added a category on the MKMapView class to encapsulate the "visible area" functionality for a very common operation: setting it to be able to see all the currently-loaded annotations on the MKMapView instance (this includes as many pins as you might have placed, as well as the user's location). the result was this:
.h file
.m file
As you can see, I've added 2 methods so far: one for setting the visible region of the map to the one that fits all currently-loaded annotations on the MKMapView instance, and another method to set it to any array of objects.
So to set the mapView's visible region the code would then be as simple as:
I hope it helps =)
此页面上的所有答案假设地图占据全屏。我实际上有一个 HUD 显示器(即分散在顶部和底部的按钮),可以在地图顶部提供信息。因此页面上的算法将正确显示引脚,但其中一些会出现在下面< /em> HUD 显示按钮。
我的解决方案将地图放大以在屏幕的子集中显示注释,并适用于不同的屏幕尺寸(即 3.5 英寸与 4.0 英寸等):
这是我的解决方案在代码中做了(注意:我使用
NSConstraints
和一些辅助方法来使我的代码在不同的屏幕尺寸下工作......而代码非常可读......我的答案 这里解释得更好..它基本上是相同的工作流程:)这里是获取适合区域的代码:
All the answers on this page assume that the map occupies the full screen. I actually have a HUD display (ie buttons scattered at the top and bottom) that give information ontop of the map.. and so the algorithms on the page will display the pins all right, but some of them will appear under the HUD display buttons.
My solution zooms the map in to display the annotations in a subset of the screen and works for different screen sizes (ie 3.5" vs 4.0" etc):
Here is what I did in code (note: i use
NSConstraints
with some helper methods to make my code work in different screen sizes.. while the code is quite readable.. my answer here explains it better.. it's basically the same workflow:)here is the code that gets region that fits:
2021 年推出 Swift 5+,
这样您就可以:
Swift 5+ in 2021
so you can just:
我对 MKMapView 类别的 Rafael 代码做了一些修改。
I've made a little modification of Rafael's code for MKMapView Category.
根据上面的答案,您可以使用通用方法来缩放地图以同时适应所有注释和叠加层。
进而:
Based on answers above you can use universal method to zoom map to fit all annotations and overlays at the same time.
And then:
只是分享我对此的观察:
如果您正在使用 xCode > 6 在故事板中使用“推断”屏幕尺寸(请参阅文件检查器上的“模拟指标”),调用
- (void)showAnnotations:(NSArray *)annotations
动画:
viewDidLoad
中的(BOOL)animated将导致4英寸iPhone上的缩放级别过大,因为地图的布局仍然是故事板中更宽屏幕的尺寸。
您可以将对
showAnnotations...
的调用移至viewDidAppear
。然后地图的大小已经调整为 iPhone 4 的较小屏幕。或者将文件检查器中“模拟指标”下的“推断”值更改为 iPhone 4 英寸。
Just sharing my observations on this:
If you are using xCode > 6 with "inferred" sizes for the screens (see "simulated metrics" on the file inspector) in storyboard, calling
- (void)showAnnotations:(NSArray *)annotations
animated:(BOOL)animated
in
viewDidLoad
will result in a too large zoom level on iPhones with 4 inches because the layout for the map is still on the size of the wider screens from the storyboard.You can move your call to
showAnnotations...
toviewDidAppear
. Then the size of the map has already been adjusted to the smaller screen of an iPhone 4.Or alternatively change the value "inferred" in the file inspector under "simulated metrics" to iphone 4-inch.
您可以选择要与注释一起显示的形状。
You can select which shapes you want to show along with the Annotations.
@“我不确定这是否是因为我的实现中的其他一些因素,但我发现 showAnnotations 并没有像手动实现那样紧密地缩放/适合注释,所以我坚持使用手动一。 – Ted Avery 4 月 17 日 0:35"
我遇到了同样的问题,但后来我尝试执行 showAnnotations 两次(如下所示),并且由于某种原因,它起作用了。
[mapView showAnnotations:yourAnnotationArray 动画:是];
[mapView showAnnotations:yourAnnotationArray 动画:是];
@"I'm not sure if this is because of some other factors in my implementation, but I find that showAnnotations doesn't do as close a zoom/fit of the annotations as the manual implementation does, so I've stuck with the manual one. – Ted Avery Apr 17 at 0:35"
I had the same problem, but then I tried doing showAnnotations twice (like below), and for some reason, it worked.
[mapView showAnnotations:yourAnnotationArray animated:YES];
[mapView showAnnotations:yourAnnotationArray animated:YES];
iOS 7 兼容的方法是使用以下方法。首先调用 showAnnotation 以获得包含所有注释的矩形。然后创建带有引脚高度顶部插入的
UIEdgeInset
。因此,您确保在地图上显示整个图钉。An iOS 7 compatible way is to use the following. First call
showAnnotation
in order to get a rectangle including all annotations. Afterwards create andUIEdgeInset
with an top inset of the pin height. Thus you ensure to show the whole pin on the map.将其相应地放入您的代码中:
Put this in to your code accordingly:
我为#Swift 5#添加了以下代码
I have added the below code for # Swift 5 #
这是我在此处找到的对我有用的:(
编辑:我已经使用@Micah的更新了解决方案建议将 pointRect 增加 0.1,以确保矩形最终不会无限小!)
您还可以通过将第一行替换为以下内容来更新此内容以包含 userLocation 引脚:
This is the one I found here that 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!)
You could also update this to include the userLocation pin by replacing the first line with: