CATiledLayer在绘制内容之前消隐拼贴

时间:2022-07-27 08:57:34

All,

所有,

I'm having trouble getting behavior that I want from CATiledLayer. Is there a way that I can trigger the tiles to redraw without having the side-effect that their areas are cleared to white first? I've already subclassed CATiledLayer to set fadeDuration to return 0.

我无法从CATiledLayer获得我想要的行为。有没有办法可以触发瓷砖重绘而没有副作用,他们的区域首先被清除为白色?我已经将CATiledLayer子类化,将fadeDuration设置为0。

To be more specific, here are the details of what I'm seeing and what I'm trying to achieve:

更具体地说,这里是我所看到的以及我正在努力实现的细节:

  • I have a UIScrollView with a big content size...~12000x800. Its content view is a UIView backed by a CATiledLayer.
  • 我有一个内容大小的UIScrollView ... ~12000x800。其内容视图是由CATiledLayer支持的UIView。
  • The UIView is rendered with a lot of custom-drawn lines
  • UIView渲染了很多自定义绘制的线条
  • Everything works fine, but the contents of the UIView sometimes change. When that happens, I'd like to redraw the tiles as seamlessly as possible. When I use setNeedsDisplay on the view, the tiles redraw but they are first cleared to white and there's a fraction-of-a-second delay before the new content is drawn. I've already subclassed CATiledLayer so that fadeDuration is set to 0.
  • 一切正常,但UIView的内容有时会改变。当发生这种情况时,我想尽可能无缝地重新绘制图块。当我在视图上使用setNeedsDisplay时,图块会重新绘制,但它们首先会被清除为白色,并且在绘制新内容之前会有一小段时间的延迟。我已经将CATiledLayer子类化,因此fadeDuration设置为0。
  • The behavior that I want seems like it should be possible...when you zoom in on the scrollview and the content gets redrawn at a higher resolution, there's no blanking before the redraw; the new content is drawn right on top of the old one. That's what I'm looking for.
  • 我想要的行为似乎应该是可能的...当您放大滚动视图并且内容以更高的分辨率重绘时,重绘之前没有消隐;新内容是在旧内容之上绘制的。这就是我在寻找的东西。

Thanks; I appreciate your ideas.

谢谢;我很感激你的想法。

Update:

更新:

Just to follow up - I realized that the tiles weren't being cleared to white before the redraw, they're being taken out entirely; the white that I was seeing is the color of the view that's beneath my CATiledLayer-backed view.

只是为了跟进 - 我意识到在重绘之前瓷砖没有被清理成白色,它们被完全取出;我看到的白色是我的CATiledLayer支持的视图下面的视图的颜色。

As a quick hack/fix, I put a UIImageView beneath the UIScrollView, and before triggering a redraw of the CATiledLayer-backed view I render its visible section into the UIImageView and let it show. This smooths out the redraw significantly.

作为一个快速入侵/修复,我在UIScrollView下面放置了一个UIImageView,在触发重新绘制CATiledLayer支持的视图之前,我将其可见部分呈现到UIImageView中并让它显示出来。这显着平滑了重绘。

If anyone has a better solution, like keeping the redraw-targeted tiles from going away before being redrawn in the first place, I'd still love to hear it.

如果有人有更好的解决方案,比如在重新绘制之前保持重绘目标图块不会消失,我仍然喜欢听到它。

5 个解决方案

#1


3  

I've found that if you set levelsOfDetailBias and levelsOfDetail both to the same value (2 in my case), then it only redraws the tiles that are touched by my setNeedsDisplayInRect: call, as you'd hope.

我发现如果你将levelsOfDetailBias和levelsOfDetail都设置为相同的值(在我的情况下是2),那么它只会重绘我的setNeedsDisplayInRect:call所触及的tile,正如你所希望的那样。

However if the levelsOfDetail is different to LODB, then any calls to setNeedsDisplayInRect: redraw all the tiles.

但是,如果levelsOfDetail与LODB不同,则对setNeedsDisplayInRect的任何调用都会重绘所有切片。

#2


1  

You could add another layer (possibly a CATiledLayer) behind the existing tiled layer. (Sort of a double-buffered solution.) You would call setNeedsDisplay: on the second layer from a timer that fires after a few seconds to ensure that that layer doesn't redraw at the same time as the front layer.

您可以在现有平铺图层后面添加另一个图层(可能是CATiledLayer)。 (双缓冲解决方案的排序。)您可以在几秒钟后触发的计时器的第二层上调用setNeedsDisplay:以确保该图层不会与前面层同时重绘。

#3


1  

Another potential option is to use the same delegate to draw content to a bitmap context and swap the bitmap into the backing store once the content is refreshed. This should produce a flicker-free result. That being said, I can't tell you how this might be done, and one nice thing about CATiledLayers is they automatically generate tiles when you zoom and pregenerate tiles when you pan once zoomed in.

另一个可能的选择是使用相同的委托将内容绘制到位图上下文,并在刷新内容后将位图交换到后备存储。这应该产生无闪烁的结果。话虽这么说,我无法告诉你如何做到这一点,而关于CATiledLayers的一个好处是,当你放大平移时缩放和预生成切片时,它们会自动生成切片。

I would like to see how you implement your application. I have been looking for weeks to find an example that uses a combination of UIScrollView and a CATiledLayer-back view with a lot of custom drawn lines. Apple has some great sample code - but it all involves images rather than line art, so no help for me.

我想看看你如何实现你的应用程序。我一直在寻找能够找到一个使用UIScrollView和CATiledLayer-back视图的组合的示例,其中包含许多自定义绘制的线条。 Apple有一些很棒的示例代码 - 但它都涉及图像而不是艺术线条,所以对我没用。

#4


0  

Having read through these answers without a solution, I discovered that tiling a page was the dominant background task.
Preparing my lo-res placeholder image on a high priority queue solved this issue - the images now appear while the tiling is occurring. Caching the placeholder images further improves their appearance - they appear before the tiling begins.
With newer devices, the tiling it so fast, these tricks might not matter. A sample PDF consisting of large scanned images (e.g. a scanned book) tiles the slowest in my experience, and makes for good test data.

在没有解决方案的情况下阅读了这些答案后,我发现平铺页面是主要的后台任务。在高优先级队列上准备我的lo-res占位符图像解决了这个问题 - 图像现在在平铺发生时出现。缓存占位符图像进一步改善了它们的外观 - 它们出现在平铺开始之前。对于较新的设备,平铺速度如此之快,这些技巧可能无关紧要。由大型扫描图像(例如扫描的书)组成的样本PDF是我体验中最慢的,并且可以获得良好的测试数据。

#5


0  

I had the same problem with iPad.

我在iPad上遇到了同样的问题。

The solution was more simple than I thought and far more simple than using UIImageView to render display before redrawing... :

解决方案比我想象的更简单,比使用UIImageView在重绘之前渲染显示要简单得多......:

Just don't set any background color for the Layer!

只是不要为图层设置任何背景颜色!

I had CATiledLayer set in a similar way:

我以类似的方式设置了CATiledLayer:

layer = [[CATiledLayer alloc] init];
layer.masksToBounds = YES;
layer.contentsGravity = kCAGravityLeft;

//layer.backgroundColor = [[UIColor whiteColor] CGColor];

layer.tileSize = CGSizeMake(1004.0, 1004.0);
layer.levelsOfDetail = 16;
layer.levelsOfDetailBias = 8;

Note that I have commented out the line setting layer's background color to white. After that the white blank before redraw problem disappeared!

请注意,我已将线设置图层的背景颜色注释为白色。之后,重绘问题之前的白色空白消失了!

Let me know if anyone has tried that.

如果有人试过,请告诉我。

#1


3  

I've found that if you set levelsOfDetailBias and levelsOfDetail both to the same value (2 in my case), then it only redraws the tiles that are touched by my setNeedsDisplayInRect: call, as you'd hope.

我发现如果你将levelsOfDetailBias和levelsOfDetail都设置为相同的值(在我的情况下是2),那么它只会重绘我的setNeedsDisplayInRect:call所触及的tile,正如你所希望的那样。

However if the levelsOfDetail is different to LODB, then any calls to setNeedsDisplayInRect: redraw all the tiles.

但是,如果levelsOfDetail与LODB不同,则对setNeedsDisplayInRect的任何调用都会重绘所有切片。

#2


1  

You could add another layer (possibly a CATiledLayer) behind the existing tiled layer. (Sort of a double-buffered solution.) You would call setNeedsDisplay: on the second layer from a timer that fires after a few seconds to ensure that that layer doesn't redraw at the same time as the front layer.

您可以在现有平铺图层后面添加另一个图层(可能是CATiledLayer)。 (双缓冲解决方案的排序。)您可以在几秒钟后触发的计时器的第二层上调用setNeedsDisplay:以确保该图层不会与前面层同时重绘。

#3


1  

Another potential option is to use the same delegate to draw content to a bitmap context and swap the bitmap into the backing store once the content is refreshed. This should produce a flicker-free result. That being said, I can't tell you how this might be done, and one nice thing about CATiledLayers is they automatically generate tiles when you zoom and pregenerate tiles when you pan once zoomed in.

另一个可能的选择是使用相同的委托将内容绘制到位图上下文,并在刷新内容后将位图交换到后备存储。这应该产生无闪烁的结果。话虽这么说,我无法告诉你如何做到这一点,而关于CATiledLayers的一个好处是,当你放大平移时缩放和预生成切片时,它们会自动生成切片。

I would like to see how you implement your application. I have been looking for weeks to find an example that uses a combination of UIScrollView and a CATiledLayer-back view with a lot of custom drawn lines. Apple has some great sample code - but it all involves images rather than line art, so no help for me.

我想看看你如何实现你的应用程序。我一直在寻找能够找到一个使用UIScrollView和CATiledLayer-back视图的组合的示例,其中包含许多自定义绘制的线条。 Apple有一些很棒的示例代码 - 但它都涉及图像而不是艺术线条,所以对我没用。

#4


0  

Having read through these answers without a solution, I discovered that tiling a page was the dominant background task.
Preparing my lo-res placeholder image on a high priority queue solved this issue - the images now appear while the tiling is occurring. Caching the placeholder images further improves their appearance - they appear before the tiling begins.
With newer devices, the tiling it so fast, these tricks might not matter. A sample PDF consisting of large scanned images (e.g. a scanned book) tiles the slowest in my experience, and makes for good test data.

在没有解决方案的情况下阅读了这些答案后,我发现平铺页面是主要的后台任务。在高优先级队列上准备我的lo-res占位符图像解决了这个问题 - 图像现在在平铺发生时出现。缓存占位符图像进一步改善了它们的外观 - 它们出现在平铺开始之前。对于较新的设备,平铺速度如此之快,这些技巧可能无关紧要。由大型扫描图像(例如扫描的书)组成的样本PDF是我体验中最慢的,并且可以获得良好的测试数据。

#5


0  

I had the same problem with iPad.

我在iPad上遇到了同样的问题。

The solution was more simple than I thought and far more simple than using UIImageView to render display before redrawing... :

解决方案比我想象的更简单,比使用UIImageView在重绘之前渲染显示要简单得多......:

Just don't set any background color for the Layer!

只是不要为图层设置任何背景颜色!

I had CATiledLayer set in a similar way:

我以类似的方式设置了CATiledLayer:

layer = [[CATiledLayer alloc] init];
layer.masksToBounds = YES;
layer.contentsGravity = kCAGravityLeft;

//layer.backgroundColor = [[UIColor whiteColor] CGColor];

layer.tileSize = CGSizeMake(1004.0, 1004.0);
layer.levelsOfDetail = 16;
layer.levelsOfDetailBias = 8;

Note that I have commented out the line setting layer's background color to white. After that the white blank before redraw problem disappeared!

请注意,我已将线设置图层的背景颜色注释为白色。之后,重绘问题之前的白色空白消失了!

Let me know if anyone has tried that.

如果有人试过,请告诉我。