簡體   English   中英

怎么把CAShapeLayer轉換成CAGradientLayer?

[英]How to Convert CAShapeLayer to 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上使用黃色到黑色的漸變。

圖片 :

在此處輸入圖片說明

在我所需的輸出中,從背景圖像中提取顏色,並在其末尾添加一些黑色,或在圖層內添加不透明度0。

任何想法,建議。

謝謝。

一個快速而骯臟的技巧是添加一個漸變層作為子層,然后再放置更多層,其背景顏色與超級視圖相同(在原始問題中為白色)。

例如:

  1. 添加一個漸變層(並設置適當的cornerRadius )。

填充漸變層

  1. 在漸變層的中心添加一個具有白色背景色的較小層(這將創建一個ring )。

環

  1. 用白色背景色創建一小段弧。

縫隙環

但是,這可能不是帶有背景圖像的合適視圖。 為了解決這個問題,您可以創建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);
}

這是視圖的完整實現

最后結果:

動畫微調器

兩環:

您可以使用以下代碼在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];

}

結果:

雙動畫環

CALayer上的mask屬性使用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]
}
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM