MKOverlayRenderer在渲染MKOverlay时被截断,但通过缩小来修复
问题描述:
我是iOS开发新手,我正在努力从iOS6移植一些涉及使用MKOverlay
的代码。MKOverlayRenderer在渲染MKOverlay时被截断,但通过缩小来修复
当叠加半径或坐标发生变化时,渲染器应该实时更新相应的显示。
这部分工作,但如果我拖动覆盖太多,它达到了一些边界和渲染被切断。我无法找到任何文档或有关此行为的帮助。
在CircleOverlayRenderer
类:
- (id)initWithOverlay:(id<MKOverlay>)overlay
{
self = [super initWithOverlay:overlay];
if (self) {
CircleZone *bOverlay = (CircleZone *)overlay;
[RACObserve(bOverlay, coordinate) subscribeNext:^(id x) {
[self setNeedsDisplay];
}];
[RACObserve(bOverlay, radius) subscribeNext:^(id x) {
[self setNeedsDisplay];
}];
}
return self;
}
- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context
{
CGRect rect = [self rectForMapRect:[self.overlay boundingMapRect]];
CGContextSaveGState(context);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextSetFillColorSpace(context, colorSpace);
CGColorSpaceRelease(colorSpace);
CGContextSetBlendMode(context, kCGBlendModeCopy);
CGContextSetFillColor(context, color);
CGContextSetAllowsAntialiasing(context, YES);
// outline
{
CGContextSetAlpha(context, 0.8);
CGContextFillEllipseInRect(context, rect);
}
// red
{
CGContextSetAlpha(context, 0.5);
CGRect ellipseRect = CGRectInset(rect, 0.01 * rect.size.width/2, 0.01 * rect.size.height/2);
CGContextFillEllipseInRect(context, ellipseRect);
}
CGContextRestoreGState(cox);
}
在CircleOverlay
类:
- (MKMapRect)boundingMapRect
{
MKMapPoint center = MKMapPointForCoordinate(self.coordinate);
double mapPointsPerMeter = MKMapPointsPerMeterAtLatitude(self.coordinate.latitude);
double mapPointsRadius = _radius * mapPointsPerMeter;
return MKMapRectMake(center.x - mapPointsRadius, center.y - mapPointsRadius,
mapPointsRadius * 2.0, mapPointsRadius * 2.0);
}
下面是我看到这个问题的一些屏幕截图:
问题拖动重叠时太太多:
更改半径时出现问题:
如果我继续缩放地图,问题确实消失。在地图磁贴刷新后,重叠不再被切断...
如果有人有类似的问题,请帮助我,这让我疯狂!
答
看看radius
的例子,它让我怀疑boundingMapRect
,鉴于它的种植情况。看boundingMapRect
的实现,依赖MKMapPointsPerMeterAtLatitude
(尤其是当你看到一个大的区域时)令人担忧。例如,如果您试图找出与某个其他坐标相距10米的坐标,但在查看非常大的跨度时,该功能非常有用,但它并不总能很好地工作。
相反,我可能会建议一些获取圆圈所在位置的MKCoordinateRegion
,然后将其转换为MKMapRect
。一个简单的实现可能是这样的:
- (MKMapRect)boundingMapRect {
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(self.coordinate, _radius * 2, _radius * 2);
CLLocationCoordinate2D upperLeftCoordinate = CLLocationCoordinate2DMake(region.center.latitude - region.span.latitudeDelta/2, region.center.longitude - region.span.longitudeDelta/2);
CLLocationCoordinate2D lowerRightCoordinate = CLLocationCoordinate2DMake(region.center.latitude + region.span.latitudeDelta/2, region.center.longitude + region.span.longitudeDelta/2);
MKMapPoint upperLeft = MKMapPointForCoordinate(upperLeftCoordinate);
MKMapPoint lowerRight = MKMapPointForCoordinate(lowerRightCoordinate);
return MKMapRectMake(MIN(upperLeft.x, lowerRight.x),
MIN(upperLeft.y, lowerRight.y),
ABS(upperLeft.x - lowerRight.x),
ABS(upperLeft.y - lowerRight.y));
}
你必须用这个来调整,以确保它优雅地处理180度经线的交叉,当圆涵盖了北极,但它说明了基本的想法: MKCoordinateRegion
为圆,然后将其转换为MKMapRect
。
我以为剪裁最初受到'boundingMapRect'的影响,但实际上改变'boundingMapRect'只会改变圆的大小。不幸的是,我仅限于我的问题中的2个链接,但拖动叠加层实际上会导致沿着相同的地图块裁剪。谢谢你让我知道'MKMapPointsPerMeterAtLatitude'的不准确性,但是在不同的缩放比例下裁剪差别很大,似乎是与比例无关的。 (更缩放它,它在更小的半径处剪辑) – kudos
我仍然认为,不正确的'boundingMapRect'(调整大小时的大小错误或拖动过程中的错误位置)将按照您在问题中说明的方式显示。请注意,如果'boundingMapRect'太小,它可以表现为不呈现整个叠加层,但是具有直接裁剪,但不一定如此。地图使用矩形图块,所以它使用'boundingMapRect'来知道哪些图块需要重新渲染。这可能是错误的大小,或者是错误的地方(或两者)。 – Rob
@ kudos - 您的图像看起来像是在手势中呈现地图,但是“boundingMapRect”可能会返回过期的值。或者你可能需要确保'boundingMapRect'计算当前的'MKMapRect',但是返回整个手势中那个和所有先前计算值的联合。但是当你随后在地图上缩小时,我会毫不犹豫地根据叠加层的正确渲染得出任何结论。这可能是瓷砖更大。这可能是很多事情。没有可重现的问题例子很难说。 – Rob