带大CATiledLayer +快速渲染的叠加层的UIScrollView [英] UIScrollView w/ Large CATiledLayer + Overlay that renders fast

查看:102
本文介绍了带大CATiledLayer +快速渲染的叠加层的UIScrollView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经研究了好几个星期了(iOS),但似乎找不到一个可以接受的解决方案。

I've been working on something for weeks now (iOS) and I can't seem to figure out an acceptable solution.

要求


  • 显示10000x10000像素的背景图像

  • 响应缩放和滚动

  • 具有自定义图形的顶部叠加层

  • 叠加层中的元素是交互式的(点击和突出显示元素等) )和片段可以打开或关闭。

  • iOS 4.0

  • Display a 10000x10000 pixel background image
  • Zooming and scrolling responsive
  • Overlay on top that has custom drawing
  • Elements in overlay are interactive (tapping and highlighting elements, etc) and pieces can be turned on or off.
  • iOS 4.0

将其视为虚构城镇的地理地图,上面疯狂地绘制着道路,线,区域和建筑物。 CGPath的混合物,其中包含各种不透明度,一些图标图像等。这就像是Google地图应用的更复杂的版本。

Think of it as a geographic map of a fictional town, with a crazy system of roads, lines, areas and buildings drawn on top. A mixture of CGPaths with fills of various opacities, some icon images etc. It's like a more complicated version of google maps app.

我尝试过的事情:

1-多个CATILed层

视图层次结构:


  • ScrollView

  • -> ContainerView

  • -> TiledView(CATiledLayer 10000x10000)

  • ---> OverlayView( CATiledLayer 10000x10000)

  • ScrollView
  • ->ContainerView
  • -->TiledView (CATiledLayer 10000x10000)
  • --->OverlayView (CATiledLayer 10000x10000)

结果:
从左侧和右侧从魔术苹果缓存中删除切片。两个CATiledlayers似乎不是正确的道路。更新覆盖图的速度并不快。

Results: Drops tiles from magic apple cache left and right. Two CATiledlayers doesn't seem to be the right path. Updates to overlay aren't fast.

2-为OverlayView子类化TiledView

视图层次结构:


  • ScrollView

  • -> OverlayView(TiledView CATiledLayer 10000x10000的子类)

结果:
花费的时间太长,无法呈现叠加层的更新。
缓慢更新图块

Results: Takes way too long to render updates for the overlay. Slow to update tiles

3-具有单个容器视图的滚动视图

查看层次结构:


  • ScrollView

  • -> ContainerView(10000x10000)

  • -> OverlayView(CALayer 10000x10000)

  • -> TiledView(CATiledLayer 10000x10000)

  • ScrollView
  • ->ContainerView (10000x10000)
  • -->OverlayView (CALayer 10000x10000)
  • -->TiledView (CATiledLayer 10000x10000)

结果:
无法工作,因为OverlayView占用了太多内存。 TileView很好,因为它由CATiledLayer支持

Results: Fails to work because OverlayView consumes too much memory. TileView is fine because it is backed by CATiledLayer

4-使用滚动委托和CTM缩放/转换的OverlayView

查看层次结构:


  • OverlayView( CALayer 1024x768)

  • ScrollView

  • -> TiledView(CATiledLayer 10000x10000)

结果:
我使用scrollview委托来调整覆盖视图的偏移和缩放。这种方法的问题在于,drawrect的调用速度约为每秒100次,并且重叠视图的绘制速度不够快,因此完全滞后于1fps。

Results: I use the scrollview delegates to adjust the offset and zoom of the overlay view. The problem with this method is that drawrect is called like 100 times a second and the overlay view can't draw fast enough so it's completely lagged down to 1fps.

这就是我的位置。我觉得这最后一种方法已经解决了,但是需要一些疯狂的工作来驯服那些懒散的疯狂。其他想法是尝试解决OpenGL中的某些问题。

So that's where I am at. I feel this last method is on to something, but would require some crazy work to tame the drawrect madness. Other thoughts would be to try to tackle something in OpenGL.

在开始做这些工作之前,我曾想过要让社区看看他们在面临类似要求时会做/已经做过的事情。

Before I go about doing those I'd thought I'd ask the community to see what they would do/have done facing similar requirements.

感谢您的帮助。

推荐答案

我的建议是在滚动视图中有两个视图。 CATiledLayer背景视图。第二个视图是位于背景视图上方的自定义UIView-在此处进行自定义绘图。自定义视图应该具有一个drawRect:方法,该方法现在什么也不做。

My suggestions is to have two views in your scrollview. The background CATiledLayer view. The second view is a custom UIView that sits above the background view - this is where you do your custom drawing. The custom view should have a drawRect: method that for now does nothing.

因此,您在customView中什么都没有尝试,并确保按需要滚动等。如果问题出在后台视图中,则需要解决此问题。

So you try this with nothing in your customView, and make sure scrolling etc is as you want it. If the problem is in the background view and you need to resolve that.

这时,您的自定义视图开始绘制内容。请注意,您将在drawRect中获得更新的矩形。也许您有一千个可能需要在整个画布上绘制的项目-因此每个项目都有一个frame属性,因此您可以确定给定的当前缩放比例并确定需要绘制的帧。您只需绘制这些项目。

At that point, your custom view starts drawing stuff. Note that you will get a rect to update in drawRect. Perhaps you have a thousand items that might need drawing over the whole canvas - so each has a frame property, so you can determine given current zoom and frame what needs to be drawn. You only draw those items.

过去,这种常规技术对我来说效果很好。

This general technique has worked well in the past for me.

EDIT2:

因此,在设备上运行时,我重复了无法分配消息。因此,计划B。您可以做的是拥有一个容器视图,该视图具有两个视图-滚动视图和新的UIView子类。 scrollView具有巨大的怪物视图。子类视图具有与UIScrollView框架完全相同的框架。

So running on a device, I duplicated the "cannot allocate" messages. So plan B. What you can do is have a container view, which has two views - the scroll view and a new UIView subclass. The scrollView has the huge monster view. The subclass view has a frame that is exactly the UIScrollView frame.

然后,请确保您获得了scrollView消息 scrollViewDidScroll:,以及其他可能的消息。

You would then make sure that you get the scrollView messages "scrollViewDidScroll:", and probably others.

当scrollView稳定时,或者您收到上述消息时,则自定义UIView子类将获得一条消息,内容为draw,但使用的是offset,即scrollView contentOffset。

When the scrollView is stable, or you et the above message, then the the custom UIView subclass gets a message that says draw but using an offset which is the scrollView contentOffset.

自定义类要做的工作是相同的。代替使用其drawRect原始点,它获取该点并将其偏移scrollView的contentOffset。现在,当您进行绘制时,您正在寻找的对象是在drawRect:rect传递的点范围内的对象,该对象正好由scrollview偏移量得出。

The work the custom class has to do is the same. Instead of using its drawRect origin point, it takes that point and offsets it by the contentOffset of the scrollView. Now, when you draw, you are looking for objects that are in scope of the point passed in the drawRect:rect offset positively by the scrollview offset.

这篇关于带大CATiledLayer +快速渲染的叠加层的UIScrollView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆