想要将MKMapView置于给定引脚下方的N个像素(当前MapRect 中可能显示或可能不显示)的位置。
我一直试图用-(CLLocationCoordinate2D)convertPoint:(CGPoint)point toCoordinateFromView:(UIView *)view
的各种剧本来解决这个问题但没有成功。
任何人都走在这条路上(没有双关语)?
答案 0 :(得分:78)
最简单的方法是将地图向下移动,比如说coordinate
所在位置的40%,利用span
的{{1}} region
}。如果您不需要实际的像素,只需要向下移动,以便所讨论的MKMapView
靠近地图的顶部(比如距离顶部10%):
CLLocationCoordinate2D
如果您想考虑相机的旋转和俯仰,上述技术可能不够用。在这种情况下,您可以:
确定要移动用户位置的视图中的位置;
将其转换为CLLocationCoordinate2D center = coordinate;
center.latitude -= self.mapView.region.span.latitudeDelta * 0.40;
[self.mapView setCenterCoordinate:center animated:YES];
;
计算当前用户位置与新的所需位置的距离;
将相机移动距离地图相机当前标题180°的方向。
E.g。在Swift 3中,类似于:
CLLocation
其中var point = mapView.convert(mapView.centerCoordinate, toPointTo: view)
point.y -= offset
let coordinate = mapView.convert(point, toCoordinateFrom: view)
let offsetLocation = coordinate.location
let distance = mapView.centerCoordinate.location.distance(from: offsetLocation) / 1000.0
let camera = mapView.camera
let adjustedCenter = mapView.centerCoordinate.adjust(by: distance, at: camera.heading - 180.0)
camera.centerCoordinate = adjustedCenter
具有以下CLLocationCoordinate2D
:
extension
因此,即使相机倾斜并且在正北方向以外的方向上,这也会移动用户的位置(位于下方十字准线的中心位置)高达150像素(上方十字线所在的位置),产生类似于:
显然,你应该意识到堕落的情况(例如你距离南极1公里,你试图将地图向上移动2公里;你使用的摄像机角度到目前为止所需的屏幕位置已经超越了地平线;等等,但对于实际的,现实世界的场景,像上面这样的东西可能就足够了。显然,如果你不让用户改变相机的音高,答案就更容易了。
原始答案:用于移动注释extension CLLocationCoordinate2D {
var location: CLLocation {
return CLLocation(latitude: latitude, longitude: longitude)
}
private func radians(from degrees: CLLocationDegrees) -> Double {
return degrees * .pi / 180.0
}
private func degrees(from radians: Double) -> CLLocationDegrees {
return radians * 180.0 / .pi
}
func adjust(by distance: CLLocationDistance, at bearing: CLLocationDegrees) -> CLLocationCoordinate2D {
let distanceRadians = distance / 6_371.0 // 6,371 = Earth's radius in km
let bearingRadians = radians(from: bearing)
let fromLatRadians = radians(from: latitude)
let fromLonRadians = radians(from: longitude)
let toLatRadians = asin( sin(fromLatRadians) * cos(distanceRadians)
+ cos(fromLatRadians) * sin(distanceRadians) * cos(bearingRadians) )
var toLonRadians = fromLonRadians + atan2(sin(bearingRadians)
* sin(distanceRadians) * cos(fromLatRadians), cos(distanceRadians)
- sin(fromLatRadians) * sin(toLatRadians))
// adjust toLonRadians to be in the range -180 to +180...
toLonRadians = fmod((toLonRadians + 3.0 * .pi), (2.0 * .pi)) - .pi
let result = CLLocationCoordinate2D(latitude: degrees(from: toLatRadians), longitude: degrees(from: toLonRadians))
return result
}
}
像素
如果你有n
,可以将其转换为CLLocationCoordinate2D
,将其移动x像素,然后将其转换回CGPoint
:
CLLocationCoordinate2D
您可以通过以下方式致电:
- (void)moveCenterByOffset:(CGPoint)offset from:(CLLocationCoordinate2D)coordinate
{
CGPoint point = [self.mapView convertCoordinate:coordinate toPointToView:self.mapView];
point.x += offset.x;
point.y += offset.y;
CLLocationCoordinate2D center = [self.mapView convertPoint:point toCoordinateFromView:self.mapView];
[self.mapView setCenterCoordinate:center animated:YES];
}
不幸的是,只有在您开始前[self moveCenterByOffset:CGPointMake(0, 100) from:coordinate];
可见时才有效,因此您可能必须先转到原始坐标,然后调整中心。
答案 1 :(得分:7)
可靠地执行此操作的唯一方法是使用以下内容:
- (void)setVisibleMapRect:(MKMapRect)mapRect edgePadding:(UIEdgeInsets)insets animated:(BOOL)animate
为了在您想要居中的地图区域的情况下执行此操作,您必须将地图区域转换为MKMapRect。显然,使用边缘填充作为像素偏移。
在此处查看: Convert MKCoordinateRegion to MKMapRect
评论:我发现这是唯一的方法,因为MKMapRect不是通常用于MKMapView的东西,所以这是唯一的方法 - 所有转换方法都适用于MKMapRegion。但是,好吧,至少它有效。在我自己的项目中测试过。
答案 2 :(得分:3)
对于Swift:
import MapKit
extension MKMapView {
func moveCenterByOffSet(offSet: CGPoint, coordinate: CLLocationCoordinate2D) {
var point = self.convert(coordinate, toPointTo: self)
point.x += offSet.x
point.y += offSet.y
let center = self.convert(point, toCoordinateFrom: self)
self.setCenter(center, animated: true)
}
func centerCoordinateByOffSet(offSet: CGPoint) -> CLLocationCoordinate2D {
var point = self.center
point.x += offSet.x
point.y += offSet.y
return self.convert(point, toCoordinateFrom: self)
}
}
答案 3 :(得分:2)
一个简单的解决方案是使地图视图的框架大于可见区域。然后将您的图钉放在地图视图的中心,并隐藏另一个视图后面或屏幕边界之外的所有不需要的区域。
让我详细说明一下。如果我查看您的屏幕截图,请执行以下操作:
您的针脚与底部之间的距离为353像素。因此,使地图视图框架的高度为两倍:706像素。截图的高度为411像素。将帧定位在706px - 411px = -293像素的原点。 现在将地图视图置于引脚坐标的中心,您就完成了。
2014年3月4日更新:
我使用Xcode 5.0.2创建了一个小型示例应用程序来演示:http://cl.ly/0e2v0u3G2q1d
答案 4 :(得分:1)
SWIFT 3更新
使用缩放
更新了功能func zoomToPos() {
let span = MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
// Create a new MKMapRegion with the new span, using the center we want.
let coordinate = moveCenterByOffset(offset: CGPoint(x: 0, y: 100), coordinate: (officeDetail?.coordinate)!)
let region = MKCoordinateRegion(center: coordinate, span: span)
mapView.setRegion(region, animated: true)
}
func moveCenterByOffset (offset: CGPoint, coordinate: CLLocationCoordinate2D) -> CLLocationCoordinate2D {
var point = self.mapView.convert(coordinate, toPointTo: self.mapView)
point.x += offset.x
point.y += offset.y
return self.mapView.convert(point, toCoordinateFrom: self.mapView)
}
答案 5 :(得分:0)
在阅读了这个线程广告后,特别是在缩放注释时,我最终得到了以下程序:
**以注释为中心:**
- (void) centerOnSelection:(id<MKAnnotation>)annotation
{
MKCoordinateRegion region = self.mapView.region;
region.center = annotation.coordinate;
CGFloat per = ([self sizeOfBottom] - [self sizeOfTop]) / (2 * self.mapView.frame.size.height);
region.center.latitude -= self.mapView.region.span.latitudeDelta * per;
[self.mapView setRegion:region animated:YES];
}
**缩放注释:**
- (void) zoomAndCenterOnSelection:(id<MKAnnotation>)annotation
{
DLog(@"zoomAndCenterOnSelection");
MKCoordinateRegion region = self.mapView.region;
MKCoordinateSpan span = MKCoordinateSpanMake(0.005, 0.005);
region.center = annotation.coordinate;
CGFloat per = ([self sizeOfBottom] - [self sizeOfTop]) / (2 * self.mapView.frame.size.height);
region.center.latitude -= self.mapView.region.span.latitudeDelta * span.latitudeDelta / region.span.latitudeDelta * per;
region.span = span;
[self.mapView setRegion:region animated:YES];
}
-(CGFloat) sizeOfBottom
和-(CGFloat) sizeOfTop
都会从布局指南中返回覆盖地图视图的面板高度
答案 6 :(得分:0)
作为公认答案的替代方法,我建议您最初的直觉是正确的。您可以严格在地图视图像素坐标空间内工作,以获得偏移量和最终定位。然后,使用从位置到屏幕视图的转换调用,您可以获取最终位置并设置地图中心。
这将在相机旋转且相对于屏幕空间的情况下起作用。在我的情况下,我需要将地图居中放置在大头针上,并有一个偏移量以说明地图抽屉。
以下是转化调用
SELECT * FROM Grades WHERE Grades.StudentID = 12
这是一个迅速的4个例子
func convert(_ coordinate: CLLocationCoordinate2D, toPointTo view: UIView?) -> CGPoint
func convert(_ point: CGPoint, toCoordinateFrom view: UIView?) -> CLLocationCoordinate2D
答案 7 :(得分:-6)
在MKMapView
上查看此方法:
- (void)setCenterCoordinate:(CLLocationCoordinate2D)coordinate animated:(BOOL)animated