官方文档
根据苹果官方文档Defining a Custom Overlay Renderer的说明,如果想要自定义Overlay显示样式,需要自定义OverlayRedner的方法
1 | - (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context |
除去这个方法之外,在 MKOverlayRenderer 的方法里还有
1 | //用于判断是否可以调用 drawMapRect:zoomScale:inContext:,默认返回 YES |
动态Overlay
动态Overlay,只需要继承 MKOverlayRenderer 实现自定义的OverlayRender
重写 drawMapRect:zoomScale:inContext: 并且在需要的调用 setNeedsDisplay 来进行刷新 就可以了
但是需要关注的一个问题是
self.overlay.boundingMapRect 会在绘制的过程中多次调用,但是仅在第一次调用时决定了该OverlayRender会被传入几次Context (重要重要)
动态绘制的关键点
结论(重要重要)
动态绘制的OverlayRender由于不确定其最终大小boundingMapRect,需要传入其可能存在的最大大小,最大为世界范围的一半(经验确定的)
1 | //实现 MKOverlay 协议的方法 |
例子
后续的文章会给出两个常用的动态Overlay的代码例子
Overlay | 文章 |
---|---|
动态圆形 | DynamicCircleOverly |
动态轨迹 | DynamicPathOverlay |
解惑(可以不看)
注释的误导
根据官方文档对 MKOverlay 的描述,其参数 boundingMapRect 仅需要最小包含当前Render的Rect
因为该方法会被多次调用,我以为其会根据每次的返回值来动态改变,根据测试发现仅在第一次时会决定其渲染的地图范围
如果范围不足,则会出现渲染的时候超出Grid的一个地图块大小时,渲染停止,因为相邻的地图块不会被传入 OverlayRender的 drawMapRect 方法
1 | // boundingMapRect should be the smallest rectangle that completely contains the overlay. |
生命周期分析
在地图加载的过程中,我们可以看到地图会被分成一个Grid(栅栏),是由一小块一小块方块组成的,在地图进行渲染的时候也是一个方块一个方块来渲染, OverlayRender的渲染结果不仅自己决定,也会受到self.overlay的方法影响
- 首先确定self.overlay中所需的MapRect大小,以及Grid中的方块数N (第一次调用boundingMapRect)
- 调用self.overlay中intersectsMapRect来确定是否可以获取boundingMapRect
- 再次调用self.overlay中boundingMapRect
- 根据boundingMapRect确定是否包含在当前MapView的可见范围
- 调用Render类中 canDrawMapRect来确定该地图块是否可以Render
- 调用Render类中 drawMapRect 来进行地图绘制
根据以上分析
- 其中 2-3步骤,会根据渲染地图Grid中的方块数决定调用几次
- 其中 4-5步骤 也会根据Grid的结果,决定调用次数,来逐个绘制
但是正如结论和上文分析,仅在 步骤1 第一次调用 boundingMapRect 会决定Grid中使用的地图方格数