Ros*_*mes 5 iphone overlay core-graphics mapkit
我使用自定义MKOverlay通过MKMapView绘制天气数据.该图纸正在CoreGraphics中完成.对于这种特殊情况,仅仅在drawMapRect:zoomScale:inContext:方法中进行绘制是不够的,因为它处理平铺的方式.我需要立即绘制整个图像,而不是像drawMapRect方法那样平铺.
之前,我在.gif中有雷达图像所以我只是添加了一个imageView并在drawMapRect中调整了imageView框架的大小.
我的计划是做一些类似的事情.添加自定义UIView并在drawMapRect中调用setNeedsDisplay.
这是相关的代码.
MKOverlay对象的boundingMapRect属性:
- (MKMapRect)boundingMapRect
{
CLLocationCoordinate2D upperLeftCoord =
CLLocationCoordinate2DMake(weatherData.radarArray.connectedRadar.latitude + 2.5,
weatherData.radarArray.connectedRadar.longitude - 2.5);
MKMapPoint upperLeft = MKMapPointForCoordinate(upperLeftCoord);
CLLocationCoordinate2D lowerRightCoord =
CLLocationCoordinate2DMake(weatherData.radarArray.connectedRadar.latitude - 2.5,
weatherData.radarArray.connectedRadar.longitude + 2.5);
MKMapPoint lowerRight = MKMapPointForCoordinate(lowerRightCoord);
double width = lowerRight.x - upperLeft.x;
double height = lowerRight.y - upperLeft.y;
MKMapRect bounds = MKMapRectMake(upperLeft.x, upperLeft.y, width, height);
return bounds;
}
Run Code Online (Sandbox Code Playgroud)
工作drawMapRect:zoomScale:inContext:代码(太慢了).
- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context {
int numPaths = parser.dataPaths.size();
// We have to pad the map rect a lot to allow for visibility testing that works well.
MKMapRect testMapRect = MKMapRectMake(mapRect.origin.x - 40000, mapRect.origin.y - 40000, mapRect.size.width + 40000, mapRect.size.height + 40000);;
// Only draw inside the area we are suppose to
//CGRect rect = [self rectForMapRect:mapRect];
//CGContextClipToRect(context, rect);
// How see through is the radar data. 1 = opaque, 0 = completely transparent
CGContextSetAlpha(context, 1);
for (int i = 0; i < numPaths; i++) {
// Make sure the bin is actually visible in this region before drawing it
if (MKMapRectContainsPoint(testMapRect, parser.dataPaths[i]->points[0]) ||
MKMapRectContainsPoint(testMapRect, parser.dataPaths[i]->points[1]) ||
MKMapRectContainsPoint(testMapRect, parser.dataPaths[i]->points[2]) ||
MKMapRectContainsPoint(testMapRect, parser.dataPaths[i]->points[3])) {
CGMutablePathRef path = CGPathCreateMutable();
CGPoint currentP = [self pointForMapPoint:parser.dataPaths[i]->points[0]];
CGContextBeginPath(context);
CGPathMoveToPoint(path, NULL, currentP.x, currentP.y);
currentP = [self pointForMapPoint:parser.dataPaths[i]->points[1]];
CGPathAddLineToPoint(path, NULL, currentP.x, currentP.y);
currentP = [self pointForMapPoint:parser.dataPaths[i]->points[2]];
CGPathAddLineToPoint(path, NULL, currentP.x, currentP.y);
currentP = [self pointForMapPoint:parser.dataPaths[i]->points[3]];
CGPathAddLineToPoint(path, NULL, currentP.x, currentP.y);
currentP = [self pointForMapPoint:parser.dataPaths[i]->points[0]];
CGPathAddLineToPoint(path, NULL, currentP.x, currentP.y);
CGPathCloseSubpath(path);
CGContextSetFillColorWithColor(context, colors[parser.dataPaths[i]->dataVal]);
CGContextAddPath(context, path);
CGContextFillPath(context);
CGPathRelease(path);
}
}
Run Code Online (Sandbox Code Playgroud)
新的drawMapRect:zoomScale:inContext:code
- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context {
// We have to pad the map rect a lot to allow for visibility testing that works well.
radarImageView.testMapRect = MKMapRectMake(mapRect.origin.x - 40000, mapRect.origin.y - 40000, mapRect.size.width + 40000, mapRect.size.height + 40000);
radarImageView.frame = [self rectForMapRect:self.overlay.boundingMapRect];
[radarImageView setNeedsDisplay];
}
Run Code Online (Sandbox Code Playgroud)
自定义UIView的drawRect方法.
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
int numPaths = parser.dataPaths.size();
CGContextSetAlpha(context, 1);
for (int i = 0; i < numPaths; i++) {
// Make sure the bin is actually visible in this region before drawing it
if (MKMapRectContainsPoint(testMapRect, parser.dataPaths[i]->points[0]) ||
MKMapRectContainsPoint(testMapRect, parser.dataPaths[i]->points[1]) ||
MKMapRectContainsPoint(testMapRect, parser.dataPaths[i]->points[2]) ||
MKMapRectContainsPoint(testMapRect, parser.dataPaths[i]->points[3])) {
CGMutablePathRef path = CGPathCreateMutable();
CGPoint currentP = [(RadarImageOverlayView *)self.superview pointForMapPoint:parser.dataPaths[i]->points[0]];
CGContextBeginPath(context);
CGPathMoveToPoint(path, NULL, currentP.x, currentP.y);
currentP = [(RadarImageOverlayView *)self.superview pointForMapPoint:parser.dataPaths[i]->points[1]];
CGPathAddLineToPoint(path, NULL, currentP.x, currentP.y);
currentP = [(RadarImageOverlayView *)self.superview pointForMapPoint:parser.dataPaths[i]->points[2]];
CGPathAddLineToPoint(path, NULL, currentP.x, currentP.y);
currentP = [(RadarImageOverlayView *)self.superview pointForMapPoint:parser.dataPaths[i]->points[3]];
CGPathAddLineToPoint(path, NULL, currentP.x, currentP.y);
currentP = [(RadarImageOverlayView *)self.superview pointForMapPoint:parser.dataPaths[i]->points[0]];
CGPathAddLineToPoint(path, NULL, currentP.x, currentP.y);
CGPathCloseSubpath(path);
CGContextSetFillColorWithColor(context, colors[parser.dataPaths[i]->dataVal]);
CGContextAddPath(context, path);
CGContextFillPath(context);
CGPathRelease(path);
}
}
}
Run Code Online (Sandbox Code Playgroud)
谢谢!
编辑
我认为这个问题与RadarImageView的上下文有关.我在drawRect:方法中获取上下文的方式有问题吗?
你不能在调用drawMapRect之前准备好你的路径吗?例如当可见区域发生变化时。您只需将路径添加到drawMapRect中的绘图上下文中。我想您甚至可以准备给定比例的路径,然后在区域更改时平移和缩放上下文(CGContextScaleCTM)。
如果数据不经常改变。另一种优化是在获得数据后立即准备 png 格式的图像以实现较低的缩放级别。对于更高的缩放级别,您可以像以前一样继续绘制。
为了减少迭代次数,您可以对数据使用平铺:您可以为每个平铺使用一个数组,而不是使用一个包含所有数据的大数组。第一步,检索与当前可见区域相交的图块对应的数组,然后仅在这些数组上循环。当然,这只适用于更高的缩放级别。
如果不想优化,可以改善显示大量路径的情况下的用户体验。为了让用户在构建路径时与地图进行交互,您不应在一个循环中处理所有元素。您可以一次处理 1000 个路径,然后使用 PerformSelector:afterDelay: 延迟处理下一批。这样您就可以显示进度条并让用户与地图交互。
| 归档时间: |
|
| 查看次数: |
6515 次 |
| 最近记录: |