简体   繁体   English

我怎么能欺骗[CALayer renderInContext:]只渲染图层的一部分?

[英]How could I trick [CALayer renderInContext: ] to render only a section of the layer?

I'm well aware that there's no nice way to render a small part of a UIView to an image, besides rendering the whole view and cropping. 我很清楚除了渲染整个视图和裁剪之外,没有很好的方法将UIView的一小部分渲染到图像中。 (VERY expensive on something like an iPad 3, where the resulting image is huge). (像iPad 3这样的产品非常昂贵,产生的图像很大)。 See here for a description of the renderInContext method (there's no alternatives). 有关renderInContext方法的说明,请参见此处 (没有替代方法)。

The part of the view that I want to render can't be predetermined, meaning I can't set up the view hierarchy for the small section to be it's own UIView (and therefore CALayer). 我想要呈现的视图部分无法预先确定,这意味着我无法将小部分的视图层次结构设置为它自己的UIView(因此也就是CALayer)。

My Idea... 我的点子...

I had an idea, but I need some direction if I'm going to succeed. 我有一个想法,但如果我要成功,我需要一些方向。 What if I create a category on UIView (or CALayer) that adds a method along the lines of: 如果我在UIView(或CALayer)上创建一个类别,该方法添加了以下方法:

[UIView renderSubframe:(CGFrame)frame];

How? 怎么样? Well, I'm thinking that if a dummy view the size of the sub frame was created, then the view could be shifted temporarily onto this. 好吧,我想如果创建子帧大小的虚拟视图,那么视图可以暂时移动到此。 Then the dummy view's layer could call renderInContext:, resulting in an efficient and fast way of getting views. 然后虚拟视图的层可以调用renderInContext:,从而获得一种有效且快速的获取视图的方法。

So... 所以...

I'm really not that up to speed with CALayer/Quartz core stuff... Will this have any chance of working? 我真的没有达到CALayer / Quartz核心的速度......这有没有机会工作? If not, what's another way I could achieve the same thing - what's the most efficient way I could achieve the same result (or has anyone else already faced this problem and come up with a different solution)? 如果没有,我可以通过另一种方式实现同​​样的目标 - 我能够实现相同结果的最有效方式是什么(或者其他人已经遇到过这个问题并提出了不同的解决方案)?

Here's the category I ended up writing. 这是我最后写的类别。 Not as hard as I first thought, thanks to a handy CGAffineTransform. 由于方便的CGAffineTransform,没有我想象的那么难。

#import "UIView+RenderSubframe.h"
#import <QuartzCore/QuartzCore.h>

@implementation UIView (RenderSubframe)

- (UIImage *) renderWithBounds:(CGRect)frame {

    CGSize imageSize = frame.size;

    UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0.0);
    CGContextRef c = UIGraphicsGetCurrentContext();

    CGContextConcatCTM(c, CGAffineTransformMakeTranslation(-frame.origin.x, -frame.origin.y));
    [self.layer renderInContext:c];

    UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return screenshot;

}

@end

A couple of different ways you might do this: 您可以通过以下几种方式执行此操作:

  1. specify a CGContextClipToRect for your context before calling renderInContext; 在调用renderInContext之前为您的上下文指定CGContextClipToRect ;

  2. use: 采用:

setNeedsDisplayInRect: setNeedsDisplayInRect:

Marks the region within the specified rectangle as needing to be updated. 将指定矩形内的区域标记为需要更新。

  - (void)setNeedsDisplayInRect:(CGRect)theRect 

This would make the rendering happen only in the specified rect. 这将使渲染仅在指定的rect中发生。 I am not sure though whether this would work as per your requirement. 我不确定这是否会按照您的要求运作。

I think that the first option should work seamlessly. 我认为第一个选项应该无缝地工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM