在绘制或填充颜色时对CAGradientLayer进行动画处理

时间:2019-05-21 10:47:05

标签: ios objective-c iphone animation calayer

我正在研究循环进度视图。我正在添加带有未选定颜色和选定颜色的圆形切片或ARC,这些颜色或颜色指示某些任务的进度。

我正在CALayers中绘制圆弧并添加动画。没有梯度的所有切片都可以正常工作。如果在任何切片/弧中添加渐变,则在立即绘制时不会设置动画。

在此问题上,请帮助我在具有CAShapeLayer的{​​{1}}中添加动画。

下面是我的代码和尝试过的方法...

注意:我尝试了三种添加动画的方法。请同时检查注释的代码

CAGradientLayer

在上面的代码中,您可以使用条件- (void)drawArcAnimation:(CGRect)rect { if (self.itemIndex >= self.sliceItems.count) { return; } float total = [self calculateTotal]; SliceItem *item = self.sliceItems[self.itemIndex]; UIBezierPath* path = [UIBezierPath bezierPath]; float angle = (item.itemValue/total) * 2 * M_PI; float endAngle = self.startAngle + angle; totalProgress += item.itemValue; if (item.shouldGradient) { // ***** This code will be used if we go for second approach of animation **** UIBezierPath *rectToAnimateFrom = [UIBezierPath bezierPathWithArcCenter:CGPointMake(rect.size.width / 2, rect.size.height / 2) radius:rect.size.width/2 - self.lineWidth startAngle:self.startAngle endAngle:self.startAngle clockwise:NO]; UIBezierPath *rectToAnimateTo = [UIBezierPath bezierPathWithArcCenter:CGPointMake(rect.size.width / 2, rect.size.height / 2) radius:rect.size.width/2 - self.lineWidth startAngle:self.startAngle endAngle:endAngle clockwise:NO]; // ***** END **** CGMutablePathRef arc = CGPathCreateMutable(); CGPathAddArc(arc, NULL, (rect.size.width / 2), (rect.size.height / 2), rect.size.width/2 - self.lineWidth, self.startAngle, endAngle, NO); self.startAngle = endAngle; CGFloat lineWidth = self.lineWidth; CGPathRef strokedArc = CGPathCreateCopyByStrokingPath(arc, NULL, lineWidth, kCGLineCapButt, kCGLineJoinMiter, // the default 10); // 10 is default miter limit CAShapeLayer *segment = [CAShapeLayer layer]; segment.fillColor = item.itemColor.CGColor; segment.strokeColor = [UIColor clearColor].CGColor; segment.path = strokedArc; // [self.baseLayer addSublayer:segment]; CAGradientLayer *gradient = [CAGradientLayer layer]; if (totalProgress > 50) { gradient.colors = @[(id)item.itemSecondaryColor.CGColor, (id)item.itemColor.CGColor,(id)item.itemColor.CGColor,(id)item.itemColor.CGColor]; }else { gradient.colors = @[(id)item.itemColor.CGColor, (id)item.itemColor.CGColor, (id)item.itemColor.CGColor,(id)item.itemSecondaryColor.CGColor]; } gradient.frame = CGPathGetBoundingBox(segment.path); CAShapeLayer *mask = [CAShapeLayer layer]; CGAffineTransform translation = CGAffineTransformMakeTranslation(-CGRectGetMinX(gradient.frame), -CGRectGetMinY(gradient.frame)); mask.path = CGPathCreateCopyByTransformingPath(segment.path, &translation); gradient.mask = mask; [self.baseLayer addSublayer:gradient]; if (_duration == 0.0) { self.itemIndex++; [self drawArcAnimation:rect]; }else { // ******* First Approach to animate ******* [CATransaction begin]; CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; drawAnimation.duration = _duration*(angle/(2 * M_PI)); drawAnimation.repeatCount = 1.0; drawAnimation.fromValue = [NSNumber numberWithFloat:0.0f]; drawAnimation.toValue = [NSNumber numberWithFloat:1.0f]; drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; [CATransaction setCompletionBlock:^{ self.itemIndex++; [self drawArcAnimation:rect]; }]; [gradient addAnimation:drawAnimation forKey:@"drawCircleAnimation"]; [CATransaction commit]; // ******* Second Approach to animate ******* // [CATransaction begin]; // CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"]; // animation.fromValue = (__bridge id _Nullable)(rectToAnimateFrom.CGPath); // animation.toValue = (__bridge id _Nullable)(rectToAnimateTo.CGPath); // animation.duration = 3; // animation.repeatCount = 1; // animation.removedOnCompletion = false; // animation.fillMode = kCAFillModeForwards; // // [CATransaction setCompletionBlock:^{ // self.itemIndex++; // [self drawArcAnimation:rect]; // }]; // // [gradient addAnimation:animation forKey:@"fill animation"]; // [CATransaction commit]; // ******* Third Approach to animate ******* // NSArray *fromColors = @[(id)UIColor.whiteColor.CGColor, (id)UIColor.clearColor.CGColor]; // NSArray *toColors = gradient.colors; // [gradient setColors:toColors]; // // [CATransaction begin]; // CABasicAnimation *animation1 = [CABasicAnimation animationWithKeyPath:@"colors"]; // animation1.fromValue = fromColors; // animation1.toValue = toColors; // animation1.duration = _duration; // animation1.removedOnCompletion = YES; // animation1.fillMode = kCAFillModeForwards; // animation1.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; // [CATransaction setCompletionBlock:^{ // self.itemIndex++; // [self drawArcAnimation:rect]; // }]; // [gradient addAnimation:animation1 forKey:@"animateGradient"]; // [CATransaction commit]; } }else { [path addArcWithCenter:CGPointMake(rect.size.width / 2, rect.size.height / 2) radius:rect.size.width/2 - self.lineWidth startAngle:self.startAngle endAngle:endAngle clockwise:YES]; self.startAngle = endAngle; CAShapeLayer *layer = [CAShapeLayer layer]; layer.path = path.CGPath; CGRect frame = path.bounds; frame.size.height = rect.size.height; frame.size.width = frame.size.width * 30; layer.strokeColor = item.itemColor.CGColor; layer.fillColor = nil; layer.lineWidth = self.lineWidth; layer.strokeStart = 0; layer.strokeEnd = 1.0; [self.baseLayer addSublayer:layer]; if (_duration == 0.0) { self.itemIndex++; [self drawArcAnimation:rect]; }else { [CATransaction begin]; CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; animation.duration = _duration*(angle/(2 * M_PI)); animation.fromValue = @(0.0); animation.toValue = @(1.0); [CATransaction setCompletionBlock:^{ self.itemIndex++; [self drawArcAnimation:rect]; }]; [layer addAnimation:animation forKey:nil]; [CATransaction commit]; } } } 及其if (item.shouldGradien)部分。动画在else的其他部分运行良好,但在渐变部分则无法运行。

我在这里做错了什么?任何帮助... ???

0 个答案:

没有答案