如何将CAShapeLayer转换为CAGradientLayer?

时间:2015-11-28 05:26:29

标签: ios cashapelayer cagradientlayer

我制作CAShapeLayer的代码是

UIBezierPath *circle = [UIBezierPath bezierPathWithArcCenter:CGPointMake(75, 125)
                                                          radius:50
                                                      startAngle:0
                                                        endAngle:1.8 * M_PI
                                                       clockwise:YES];

    CAShapeLayer *circleLayer = [CAShapeLayer layer];
    [circleLayer setFrame:CGRectMake(200 - 50, 300 - 50, 100, 100)];
    circleLayer.path   = circle.CGPath;
    circleLayer.bounds = CGPathGetBoundingBox(circle.CGPath);
    circleLayer.strokeColor = [UIColor colorWithRed:0.4 green:1.0 blue:0.2 alpha:0.5].CGColor;
    [circleLayer setFillColor:[UIColor clearColor].CGColor];
    circleLayer.lineWidth   = 3.0;

    if ([circleLayer animationForKey:@"SpinAnimation"] == nil) {
        CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
        animation.fromValue = [NSNumber numberWithFloat:0.0f];
        animation.toValue = [NSNumber numberWithFloat: 2 * M_PI];
        animation.duration = 2.0f;
        animation.repeatCount = INFINITY;
        animation.removedOnCompletion = NO;
        [circleLayer addAnimation:animation forKey:@"SpinAnimation"];
    }
    [self.view.layer addSublayer:circleLayer];

我想制作CAGradientLayer而不是CAShapeLayer。

原因:我需要在图层中使用渐变色,这在CAShapeLayer中是不可能的。

我想在Cirle上使用黄色到黑色渐变。

图片:

enter image description here

在我需要的输出中,从背景图像中提取颜色,并在最后添加一些黑色,或在图层中添加不透明度。

任何想法,建议。

感谢。

2 个答案:

答案 0 :(得分:4)

一个快速而肮脏的技巧是添加一个渐变图层作为子图层,然后再添加一些背景颜色与超视图相同的图层(在原始问题中,它是白色的)。

例如:

  1. 添加渐变图层(并设置正确的cornerRadius)。
  2. filled gradient layer

    1. 在渐变图层的中心添加一个白色背景颜色的较小图层(这将创建响铃)。
    2. ring

      1. 使用白色背景颜色创建一小段弧。
      2. ring with gap

        但是,这可能不适合使用背景图像。 要解决此问题,您可以创建UIView的自定义子类并覆盖drawRect方法。

        假设存在实例变量:startColorendColorradiusstrokeWidthmirrored

        变量mirrored用于控制间隙的位置(切除左侧或右侧)和动画的旋转方向(顺时针或逆时针)。

        - (void)drawRect:(CGRect)rect
        {
            CGContextRef ctx = UIGraphicsGetCurrentContext();
        
            CGContextSetBlendMode(ctx, kCGBlendModeNormal);
        
            CGFloat gradientColors[4 * 2];
        
            extractColorComponents(_startColor, gradientColors, 0);
            extractColorComponents(_endColor, gradientColors, 4);
        
        
            CGColorSpaceRef baseSpace = CGColorSpaceCreateDeviceRGB();
            CGGradientRef gradient = CGGradientCreateWithColorComponents(baseSpace, gradientColors, NULL, 2);
            CGColorSpaceRelease(baseSpace);
            baseSpace = nil;
        
            CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
            CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));
            CGContextDrawLinearGradient(ctx, gradient, startPoint, endPoint, 0);
            CGGradientRelease(gradient);
            gradient = nil;
        
            // fill 'clear' color
            CGContextSetFillColorWithColor(ctx, [UIColor clearColor].CGColor);
            CGContextSetStrokeColorWithColor(ctx, [UIColor clearColor].CGColor);
        
            CGContextSetBlendMode(ctx, kCGBlendModeClear);
        
            CGFloat innerCircleRadius = _radius - _strokeWidth;
        
            // fill an 'empty' hole inside the gradient part
            CGContextFillEllipseInRect(ctx, (CGRect){
                {_strokeWidth, _strokeWidth},
                {innerCircleRadius * 2, innerCircleRadius * 2}
            });
        
        
            // fill an 'empty' segment of arc
            CGFloat startAngle = _mirrored ? (0.9 * M_PI) : (-0.1 * M_PI);
            CGFloat endAngle = startAngle + 0.2 * M_PI;
            UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:(CGPoint){_radius, _radius}
                                                                radius:_radius - _strokeWidth * 0.5
                                                            startAngle:startAngle
                                                              endAngle:endAngle
                                                             clockwise:YES];
            path.lineWidth = _strokeWidth;
            CGContextAddPath(ctx, path.CGPath);
            CGContextSetLineWidth(ctx, _strokeWidth + 2);
            CGContextStrokePath(ctx);
        
            CGContextSetBlendMode(ctx, kCGBlendModeNormal);
        }
        

        此处是视图的complete implementation

        最终结果:

        animated spinner

        两响:

        您可以使用以下代码在viewDidLoad或其他地方添加两个响铃以获得所需效果:

        - (void)viewDidLoad 
        {
            [super viewDidLoad];
        
            UIColor *startColor = [UIColor colorWithHue:0.02 saturation:0.74 brightness:0.91 alpha:1];
            UIColor *endColor = [UIColor colorWithHue:0.57 saturation:0.76 brightness:0.86 alpha:1];
        
            CGPoint center = CGPointMake(160, 200);
        
            Spinner *outerSpinner = [[Spinner alloc] initWithCenter:center
                                                             radius:50
                                                        strokeWidth:3
                                                         startColor:startColor
                                                           endColor:endColor
                                                           mirrored:NO];
        
            Spinner *innerSpinner = [[Spinner alloc] initWithCenter:center
                                                             radius:40
                                                        strokeWidth:3
                                                         startColor:startColor
                                                           endColor:endColor
                                                           mirrored:YES];
        
        
            [self.view addSubview:outerSpinner];
            [self.view addSubview:innerSpinner];
        
            [outerSpinner startAnimating];
            [innerSpinner startAnimating];
        
        }
        

        结果:

        double animated rings

答案 1 :(得分:-1)

CALayer上的mask属性使用遮罩层的alpha分量来确定应该可见的内容,而不是。由于您的两种颜色(黑色和白色)都是完全不透明的(没有透明度),因此蒙版无效。要解决此问题,您应该将其中一种颜色更改为清晰的颜色:

gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor blackColor] CGColor], 
                                            (id)[[UIColor clearColor] CGColor], nil];

修改

class Colors {
let colorTop = UIColor(red: 192.0/255.0, green: 38.0/255.0, blue: 42.0/255.0, alpha: 1.0).CGColor
let colorBottom = UIColor(red: 35.0/255.0, green: 2.0/255.0, blue: 2.0/255.0, alpha: 1.0).CGColor

let gl: CAGradientLayer

init() {
    gl = CAGradientLayer()
    gl.colors = [ colorTop, colorBottom]
    gl.locations = [ 0.0, 1.0]
}
}