简体   繁体   English

如何将CALayer子类化为另一个CALayer掩码?

[英]How to subclass CALayer for use as another CALayer mask?

I' m trying to subclass CALayer for use as a mask on another layer. 我正在尝试将CALayer子类化为另一层上的掩码。

I want to use my CALayer subclass in place of a CAGradientLayer and use it for a gradient mask as explained here . 我想用我的CALayer子类来代替的CAGradientLayer并使用它的灰度掩模作为解释在这里

However I wish to use a custom CALayer that uses an internal CGGradient for drawing instead, as this should produce smoother results than CAGradientLayer ( see here ). 但是我希望使用一个使用内部CGGradient进行绘制的自定义CALayer ,因为这样可以产生比CAGradientLayer更平滑的结果( 参见此处 )。 I don't care about performance, I want better gradient quality. 我不关心性能,我想要更好的渐变质量。

I'm following this example for creating my CGGradient and storing it on the CALayer .. However, I cannot get the mask to draw. 我正在按照这个例子创建我的CGGradient并将其存储在CALayer 。但是,我无法绘制掩码。

I don't know where to put the draw code: CALayer 's display nor drawInContext:(CGContextRef)ctx nor drawInContext:(CGContextRef)ctx seem to be called when it is used as a mask. 我不知道在哪里放置绘图代码: CALayerdisplay也不是drawInContext:(CGContextRef)ctx也不是drawInContext:(CGContextRef)ctx似乎在用作掩码时被调用。

Bear with me as I'm new with CoreAnimation. 跟我一起玩,因为我是CoreAnimation的新手。 So, how to fix this so my CALayer subclass works as a replacement for CAGradientLayer but draws using a CGGradient ? 那么,如何解决这个问题,以便我的CALayer子类可以替代CAGradientLayer但是使用CGGradient绘制?


My current code here: 我目前的代码在这里:

@interface CANiceGradientLayer : CALayer

@property (nonatomic) CGGradientRef gradient;
@property (atomic) CGPoint startPoint;
@property (atomic) CGPoint endPoint;

@end

@implementation CANiceGradientLayer

- (instancetype)initWithGradientRef:(CGGradientRef)gradient startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint
{
    if ( !(self = [super init]) )
    {
        return nil;
    }

    self.gradient = CGGradientRetain(gradient);
    self.startPoint = startPoint;
    self.endPoint = endPoint;

    return self;
}

- (void)dealloc
{
    CGGradientRelease(self.gradient);
}

- (void)display
{
    NSLog(@"display");
}

- (void)drawInContext:(CGContextRef)ctx
{
    NSLog(@"drawInContext:");
    CGContextDrawLinearGradient(ctx, self.gradient, self.startPoint, self.endPoint, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);;
}

- (void)renderInContext:(CGContextRef)ctx
{
    NSLog(@"renderInContext:");
}

@end

And here is how I create it: 以下是我创建它的方法:

size_t num_locations = 2;
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = { 1.0, 1.0, 1.0, 1.0,  // Start color
                          1.0, 1.0, 1.0, 0.0 }; // End color

CGColorSpaceRef rgbColorspace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);


self.collectionViewTickerMaskLayer = [[CANiceGradientLayer alloc] initWithGradientRef:gradient startPoint:CGPointZero endPoint:CGPointZero];


self.collectionViewTickerMaskLayer.anchorPoint = CGPointZero;
view.layer.mask = self.collectionViewTickerMaskLayer;

If I use a CAGradientLayer instead, it works fine (but the gradient looks bad). 如果我使用CAGradientLayer ,它工作正常(但渐变看起来很糟糕)。

Call -setNeedsDisplay on your layer subclass before setting it to the mask and you'll only need to override -drawInContext: of the CALayer subclass. 在将图层设置为蒙版之前,在图层子类上调用-setNeedsDisplay ,您只需要覆盖CALayer子类的-drawInContext: . That will help you get the method to be called (CALayer calls -drawInContext: using its default implementation of -display which is called after -setNeedsDisplay ). 这将帮助你要调用的方法(CALayer的调用-drawInContext:使用它的默认实现-display被称为后-setNeedsDisplay )。 You may also have to set the frame of the layer: 您可能还需要设置图层的框架:

self.collectionViewTickerMaskLayer.frame = view.layer.bounds;
self.collectionViewTickerMaskLayer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;

You have a logic issue in this code. 您在此代码中遇到了逻辑问题。 You are using an endpoint which is CGPointZero, so even if the methods were called, no gradient would even be drawn to mask your layer. 您使用的是CGPointZero端点,因此即使调用了这些方法,也不会绘制任何渐变来掩盖您的图层。

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

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