简体   繁体   English

用UIBezierPath的CAShapeLayer遮罩时,CAGradientLayer意外输出

[英]CAGradientLayer unexpected output when masked with CAShapeLayer from UIBezierPath

I'm using this sample code from Palimondo : it is brilliant code learning how to mask CAGradientLayer's onto CAShapeLayers. 我使用的是来自Palimondo的 示例代码 :这是学习如何将CAGradientLayer遮罩到CAShapeLayers上的出色代码。 The Output is as follows: 输出如下:

在此处输入图片说明

Now I am trying to create this image: 现在,我尝试创建此图像:

在此处输入图片说明

Using PaintCode, I was able to get all the UIBezierPath's and Gradient Colors and stops and put them into multiple Arrays, and essentially iterate through each one adding it to new CAShapeLayer and CAGradientLayer as such: 使用PaintCode,我能够获取所有UIBezierPath和Gradient Colors并将其停下来并将它们放入多个Array中,并本质上进行遍历,依次将其添加到新的CAShapeLayer和CAGradientLayer中,如下所示:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self blackPaths];
    [self setupGradients];
    int count = 0;
    for (CAGradientLayer *gradientLayerItem in _individualGradientArrays) {

        CAShapeLayer *gradientMask = [CAShapeLayer layer];
        gradientMask.fillColor = [[UIColor clearColor] CGColor];
        gradientMask.strokeColor = [[UIColor blackColor] CGColor];
        gradientMask.lineWidth = 4;
        gradientMask.frame = CGRectMake(0, 0, _testView.bounds.size.width, _testView.bounds.size.height);
        //
        //    CGMutablePathRef t = CGPathCreateMutable();
        //    CGPathMoveToPoint(t, NULL, 0, 0);
        //    CGPathAddLineToPoint(t, NULL, _testView.bounds.size.width, _testView.bounds.size.height);

        gradientMask.path = [[_UIBezierPathsArray objectAtIndex:count]CGPath];


        CAGradientLayer *gradientLayer = [CAGradientLayer layer];
        gradientLayer.locations = gradientLayerItem.locations;
        gradientLayer.startPoint = CGPointMake(0.5,1.0);
        gradientLayer.endPoint = CGPointMake(1.0,0.5);
        gradientLayer.frame = CGRectMake(0, 0, _testView.bounds.size.width, _testView.bounds.size.height);
        //    NSMutableArray *colors = [NSMutableArray array];
        //    for (int i = 0; i < 3; i++) {
        //        [colors addObject:(id)[[UIColor colorWithHue:(0.2 * i) saturation:1 brightness:.8 alpha:1] CGColor]];
        //    }
        gradientLayer.colors = gradientLayerItem.colors;

        [gradientLayer setMask:gradientMask];
        [_testView.layer addSublayer:gradientLayer];
        count++;
    }

[_testView setNeedsDisplay];

The goal is to have 16 individual CAGradientLayer's that I can animate using CoreAnimation to create a sort of "swirling" effect (I could just place the output from PaintCode into a drawRect, and it works, the problem is that I was told that I would have a much more difficult time animating either the colors or gradients via CoreGraphics rather than placing them in Layers). 我的目标是要有16个独立的CAGradientLayer,可以使用CoreAnimation进行动画处理以创建一种“旋转”效果(我可以将PaintCode的输出放置到drawRect中,并且可以正常工作,问题是我被告知要通过CoreGraphics为颜色或渐变设置动画,而不是将它们放置在“图层”中要花很多时间。

And then, this is outputed: 然后,输出:

70年代的舞会版本...

After 100's of iterations and before this point, I tried swaping out the [UIColor clearColor] for whiteColor (Which is not what the sample code required) and this is outputted: 经过100次迭代之后,在此之前,我尝试将[UIColor clearColor] whiteColor (这不是示例代码所要求的),并输出:

快好了...

You can see there is only a couple of gradients, and it is my belief the whiteColor is interfering with the CAGradientLayer. 您可以看到只有几个渐变,我相信whiteColor会干扰CAGradientLayer。

I know I must be missing something extremely subtle, but I can't seem to see it. 我知道我一定会错过一些极其微妙的东西,但是我似乎看不到它。

Why is it that in the example code, we are able to use clearColor and have the gradient show up appropriately, yet using clearColor with my UIBezierPath's attached to my CAShapeLayer's the gradients break? 为什么在示例代码中,我们能够使用clearColor并正确显示渐变,但是将clearColor与UIBezierPath附加到我的CAShapeLayer的渐变之间却可以使用?

A friend mentioned that another solution would be to have 3 circles of the gradients and basically rotate them concentrically over the masked shape creating the illusion, however I am at a loss how I would be able to do that. 一位朋友提到,另一种解决方案是使3个渐变圆基本上在同一个蒙版形状上同心旋转,以创建幻觉,但是我不知该如何做到。

It's hard to say from what's here exactly what's going on. 从这里到底发生了什么很难说。 In the third picture (based on your code) you're drawing opaque, black strokes around a clear fill into the mask, so when you use that as a mask, only the areas you stroked will be "visible" from the gradient layer (the hint that these are strokes only is that you can see the stroke miters). 在第三张图片中(基于您的代码),您在遮罩中的透明填充周围绘制了不透明的黑色描边,因此,当您将其用作遮罩时,只有被描边的区域才对渐变层“可见”(这些只是笔画的提示是您可以看到笔画斜线。 When you change clearColor to whiteColor (which is opaque), the area inside the path also becomes visible from the gradient layer (the hint to this is that the lines appear fatter owing to the fact that the stroke runs along the middle of the path, thus "fattening" the fill. Also the stroke miters are no longer visible because they've been occluded by the fill.) 当将clearColor更改为whiteColor(不透明)时,路径内部的区域也将从渐变层变为可见(这提示线条由于路径沿路径的中间延伸而显得较粗,从而“填充”填充。此外,笔划斜线不再可见,因为它们已被填充所遮挡。)

In a mask layer, the color is irrelevant -- it's the alpha channel (opacity) that matters. 在遮罩层中,颜色无关紧要-重要的是Alpha通道(不透明度)。 This is why whiteColor vs. blackColor makes no difference. 这就是为什么whiteColor与blackColor没有区别的原因。 They both have an alpha value of 1.0, whereas clearColor has an alpha value of 0.0. 它们的alpha值均为1.0,而clearColor的alpha值为0.0。 From the header: 从标题:

/* A layer whose alpha channel is used as a mask to select between the
 * layer's background and the result of compositing the layer's
 * contents with its filtered background. Defaults to nil. When used as
 * a mask the layer's `compositingFilter' and `backgroundFilters'
 * properties are ignored. When setting the mask to a new layer, the
 * new layer must have a nil superlayer, otherwise the behavior is
 * undefined. */

@property(retain) CALayer *mask;

This is why you no longer see the stroke miters in the fourth image -- they're being hidden by the fact that the mask only looks at the alpha channel and regardless of color hue (ie white or black) they both paint with an alpha of 1.0. 这就是为什么您不再在第四张图像中看到笔划斜线笔的原因-它们被遮罩掩盖了,因为该遮罩仅查看alpha通道,并且不管它们的色相(即白色或黑色)都用alpha笔画的1.0。

Again, it's not clear exactly what you're trying to do here in the end, but your use of whiteColor feels like a red herring. 再次强调,您到底要在这里做什么并不确定,但是您对whiteColor的使用感觉就像是一条红色的鲱鱼。 If your goal is something that looks like the second image, you probably want your mask layer to have no stroke and an opaque fill, as in: 如果您的目标看起来像第二张图像,则可能希望蒙版层没有笔触和不透明填充,如下所示:

gradientMask.fillColor = [[UIColor blackColor] CGColor];
gradientMask.strokeColor = [[UIColor clearColor] CGColor];

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

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