我一直在研究现有 MKMapView 的简单路径覆盖。它采用 CGMutablePath 并将其绘制到地图上。目标是绘制代表实际宽度的路径。例如,子类采用以米为单位的宽度并将该宽度转换为代表线宽。这是计算线宽的代码的一个版本:
- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context
float mapPoints = meterWidth * MKMapPointsPerMeterAtLatitude(self.averageLatitude);
float screenPoints = mapPoints * zoomScale; // dividing would keep the apparent width constant
self.lineWidth = ceilf(screenPoints * 2);
CGContextAddPath(context, _mutablePath);
[self applyStrokePropertiesToContext:context atZoomScale:zoomScale];
CGContextStrokePath(context);
在这里,我们首先找到与我们的线宽相对应的地图点数,然后将其转换为屏幕点数。我们根据 MKGeometry.h 中的标题注释进行转换:
// MKZoomScale provides a conversion factor between MKMapPoints and screen points.
// When MKZoomScale = 1, 1 screen point = 1 MKMapPoint. When MKZoomScale is
// 0.5, 1 screen point = 2 MKMapPoints.
最后,我们将路径添加到上下文中,将描边属性应用于路径并对其进行描边。
然而,这给出了非常不稳定的结果。渲染器经常在预期的活动区域之外的各个地方随机绘制线条片段,或者根本不绘制一些图块。有时,CPU 会一遍又一遍地重绘同一个图块的多个版本(据我所知)。在这种情况下,文档并没有太大帮助。
我确实有一个工作版本,但它似乎不是正确的解决方案,因为它完全忽略了 zoomScale 并且不使用 -applyStrokePropertiesToContext:atZoomScale:
float mapPoints = meterWidth * MKMapPointsPerMeterAtLatitude(self.averageLatitude);
self.lineWidth = ceilf(mapPoints * 2);
CGContextAddPath(context, _mutablePath);
CGContextSetStrokeColorWithColor(context, self.strokeColor.CGColor);
CGContextSetLineWidth(context, self.lineWidth);
CGContextSetLineJoin(context, kCGLineJoinRound);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextStrokePath(context);
任何人都有关于这个实现有什么问题的指针?