[英]How to Convert CAShapeLayer to CAGradientLayer?
my code of making CAShapeLayer is 我制作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];
I want to make CAGradientLayer instead of CAShapeLayer. 我要制作CAGradientLayer而不是CAShapeLayer。
REASON: I need to use gradient color in layer, which is not possible in CAShapeLayer. 原因:我需要在图层中使用渐变颜色,这在CAShapeLayer中是不可能的。
I want to use yellow to black gradient upon Cirle. 我想在Cirle上使用黄色到黑色的渐变。
Image : 图片 :
In my required output, color is fetched from background image, and put some black at the end, or opacity 0 within layer. 在我所需的输出中,从背景图像中提取颜色,并在其末尾添加一些黑色,或在图层内添加不透明度0。
Any Idea, suggestion. 任何想法,建议。
Thanks. 谢谢。
One quick and dirty trick is adding a gradient layer as a sublayer then put some more layers with the background colors same as the superview (in the original question, it's white). 一个快速而肮脏的技巧是添加一个渐变层作为子层,然后再放置更多层,其背景颜色与超级视图相同(在原始问题中为白色)。
For example: 例如:
cornerRadius
). cornerRadius
)。 However, this may not be suitable views with background images. 但是,这可能不是带有背景图像的合适视图。 To solve this, you can create a custom subclass of
UIView
and override the drawRect
method. 为了解决这个问题,您可以创建
UIView
的自定义子类并重写drawRect
方法。
Suppose there are instance variables: startColor
, endColor
, radius
, strokeWidth
, and mirrored
. 假设有实例变量:
startColor
, endColor
, radius
, strokeWidth
和mirrored
。
The variable mirrored
is used to control the position of the gap (cut off left side or right side) and the rotation direction of the animation (clockwise or counter-clockwise). 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);
}
Here's the complete implementation of the view. 这是视图的完整实现 。
Final result: 最后结果:
Two rings: 两环:
You can add two rings in your viewDidLoad
or somewhere else with the following code to achieve the desired effect: 您可以使用以下代码在
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];
}
Result: 结果:
The mask property on CALayer uses the alpha component of the mask layer to determine what should be visible and not. CALayer上的mask属性使用mask图层的alpha分量来确定哪些内容应该可见,哪些不可见。 Since both of your colors (black and white) are fully opaque (no transparency) the mask has no effect.
由于两种颜色(黑色和白色)都完全不透明(没有透明度),因此遮罩无效。 To fix this you should change one of the colors to a clear color:
要解决此问题,您应该将一种颜色更改为清晰的颜色:
gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor blackColor] CGColor],
(id)[[UIColor clearColor] CGColor], nil];
EDIT 编辑
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.