带有大型CATiledLayer的UIScrollView +渲染速度快的Overlay
我一直在努力工作几个星期(iOS),我似乎无法找出一个可以接受的解决scheme。
要求
- 显示一个10000×10000像素的背景图像
- 缩放和滚动响应
- 覆盖在具有自定义绘图的顶部
- 叠加中的元素是交互式的(点击和突出显示元素等),可以打开或closures棋子。
- iOS 4.0
把它想象成一个虚构的小镇的地理地图,在上面绘制一个疯狂的道路,线路,区域和build筑系统。 CGPaths与各种不透明的填充,一些图标图像等混合物。这就像一个更复杂的谷歌地图应用程序的版本。
我试过了:
1 – 多个CATiled图层
查看层次结构:
- 滚动型
- – > ContainerView
- – > TiledView(CATiledLayer 10000×10000)
- —> OverlayView(CATiledLayer 10000×10000)
结果:从魔法苹果caching中左右丢弃瓦片。 两个CATiledlayers似乎不是正确的道路。 更新重叠不是很快。
2 – 用于OverlayView的子类TiledView
查看层次结构:
- 滚动型
- – > OverlayView(TiledView CATiledLayer 10000×10000的子类)
结果:渲染覆盖的更新时间过长。 慢点更新瓷砖
3 – 滚动视图w /一个容器视图
查看层次结构:
- 滚动型
- – > ContainerView(10000×10000)
- – > OverlayView(CALayer 10000×10000)
- – > TiledView(CATiledLayer 10000×10000)
结果:因为OverlayView消耗太多的内存,所以无法工作。 TileView很好,因为它由CATiledLayer支持
4 – 使用滚动委托和CTM比例/翻译来模拟大的OverlayView
查看层次结构:
- OverlayView(CALayer 1024×768)
- 滚动型
- – > TiledView(CATiledLayer 10000×10000)
结果:我使用scrollview委托来调整覆盖视图的偏移和缩放。 这个方法的问题是,drawrect被称为每秒100次,overlay视图不能足够快,所以它完全落后到1fps。
那就是我所在的地方。 我觉得这最后一种方法是有用的,但是需要一些疯狂的工作来驯服疯狂的疯狂。 其他的想法是试图解决OpenGL中的东西。
在我开始做这些事之前,我曾想过要求社区看看他们会做些什么,或者做些什么来面对类似的要求。
谢谢你的帮助。
我的build议是在你的滚动视图中有两个视图。 后台CATiledLayer视图。 第二个视图是位于背景视图上方的自定义UIView – 这是您自定义绘图的位置。 自定义视图应该有一个drawRect:方法,现在什么都不做。
所以你在你的customView中没有任何东西,并确保滚动等是你想要的。 如果问题出现在背景视图中,则需要解决该问题。
在这一点上,你的自定义视图开始绘制的东西。 请注意,您将得到一个rect在drawRect中更新。 也许你有一千个项目可能需要在整个canvas上画 – 所以每个都有一个框架属性,所以你可以确定给定的当前缩放和框架需要绘制。 你只画这些项目。
这个通用技术在过去对我来说工作得很好。
EDIT2:
所以在设备上运行,我复制了“无法分配”消息。 所以计划B.你可以做的是有一个容器视图,它有两个视图 – 滚动视图和一个新的UIView子类。 scrollView有巨大的怪物视图。 子类视图有一个框架,就是UIScrollView框架。
然后你会确保你得到scrollView消息“scrollViewDidScroll:”,可能还有其他的。
当scrollView是稳定的,或者你et上面的消息,那么自定义的UIView子类会得到一个消息,说绘制,但使用scrollView contentOffset的偏移量。
自定义类必须做的工作是一样的。 而不是使用它的drawRect原点,它取得了这一点,并通过scrollView的contentOffset偏移它。 现在,当您绘制时,您正在通过滚动视图偏移正面查找在drawRect:rect偏移量中传递的点范围内的对象。
我绘制了一个基于path的地图,但是我没有背景图片,只有path。 我只用了一个View(没有滚动视图),自己实现了滚动/缩放。 那里有一些性能问题,特别是在高分辨率的ipad3,因为它有分配全分辨率imagecontext的问题。
- 不要在path上使用阴影等,这会杀死你的performance。
- 预先计算path/对象的所有边界框,并按照某种顺序存储它们,以便尽可能快地查找可见path/对象。
- 为不同的缩放级别使用不同的详细path。
但最后我认为openGL是更好的解决scheme。
老问题,但每个人都在为此苦苦挣扎。 您应该使用两个以相同方式放大/滚动的“平铺视图”,但叠加视图不应该是背景视图的子视图。 那就是,你应该有:
- 滚动型
- – > ContainerView
- – > TiledView(CATiledLayer 10000×10000)
- – > OverlayView(CATiledLayer 10000×10000)
然后,为了绘制速度,这实际上取决于你如何绘制覆盖图。 对于每个图块,您应该确保只绘制覆盖图块的图块,而不是所有其他的图块边界之外的东西。