2014-11-05 81 views
3

我试图实现一个循环指标,随着值的变化绘制动画本身。我使用CAShapeLayer来绘制动画。到目前为止,我每次都从头开始吸收它,它按预期工作。现在我想让它变得更加圆滑,并且将它拉到前面并根据新值是大于还是小于前一个值来“擦除”。我不知道如何实现删除部分。有背景,所以我不能用白色在上面画。这是一张图片,可以更好地了解它的外观。iOS的“擦除”与动画CAShapeLayer绘图

Circular indicator

任何想法擦除部如何才能实现?对于类似的问题,这里有一些解决方案,但那些不涉及动画。

我用这个代码绘制:

- (void)drawCircleAnimatedWithStartAngle:(CGFloat)startAngle 
          endAngle:(CGFloat)endAngle 
           color:(UIColor *)color 
           radius:(int)radius 
          lineWidth:(int)lineWidth { 


CAShapeLayer *circle = [CAShapeLayer layer]; 
circle.name = @"circleLayer"; 

    circle.path = ([UIBezierPath bezierPathWithArcCenter:CGPointMake(radius, radius) radius:radius-1 startAngle:startAngle endAngle:endAngle clockwise:YES].CGPath); 

// Configure the apperence of the circle 
circle.fillColor = [UIColor clearColor].CGColor; 
circle.strokeColor = [UIColor colorWithRed:19.0/255 green:167.0/255 blue:191.0/255 alpha:1].CGColor; 
circle.lineWidth = lineWidth; 

// Add to parent layer 
for (CALayer *layer in self.circleView.layer.sublayers) { 
    if ([layer.name isEqualToString:@"circleLayer"]) { 
     [layer removeFromSuperlayer]; 
     break; 
    } 
} 

[self.circleView.layer addSublayer:circle]; 
circle.zPosition = 1; 


// Configure animation 
CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; 
drawAnimation.duration   = 0.5; 
drawAnimation.repeatCount   = 1.0; // Animate only once.. 

// Animate from no part of the stroke being drawn to the entire stroke being drawn 
drawAnimation.fromValue = [NSNumber numberWithFloat:0.0f]; 
drawAnimation.toValue = [NSNumber numberWithFloat:1.0f]; 

drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 

// Add the animation to the circle 
[circle addAnimation:drawAnimation forKey:@"drawCircleAnimation"]; 

} 

回答

6

我能够从你在做什么,这样做在一个稍微不同的方式。我没有画出一定长度的弧线,而是让自己的路线成了一个整圈,但只能让它变成一部分。您会注意到我使用表示层的strokeEnd来获取toValue,所以如果在需要更改最终strokeEnd的值时正在进行动画,它将从当前绘制路径的位置开始。这是我的视图控制器中的代码;轮廓图层绘制灰色圆圈,类似于图像中的图像。我加入5个按键我的视图(用于测试),其标记用于改变动画的最终行程值,

@implementation ViewController { 
    UIView *circleView; 
    RDShapeLayer *circle; 
} 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    circleView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)]; 
    CALayer *outlineLayer = [CALayer new]; 
    outlineLayer.frame = circleView.bounds; 
    outlineLayer.borderWidth = 2; 
    outlineLayer.borderColor = [UIColor lightGrayColor].CGColor; 
    outlineLayer.cornerRadius = circleView.frame.size.width/2.0; 
    [circleView.layer addSublayer:outlineLayer]; 
    [self.view addSubview:circleView]; 

    circle = [[RDShapeLayer alloc] initWithFrame:circleView.bounds color:[UIColor blueColor].CGColor lineWidth:4]; 
    [circleView.layer addSublayer:circle]; 
} 


-(void)animateToPercentWayAround:(CGFloat) percent { 

    circle.strokeEnd = percent/100.0; 
    CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; 
    drawAnimation.duration = 1.0; 
    drawAnimation.fromValue = @([circle.presentationLayer strokeEnd]); 
    drawAnimation.toValue = @(percent/100.0); 

    drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 
    [circle addAnimation:drawAnimation forKey:@"drawCircleAnimation"]; 
} 


- (IBAction)changeStroke:(UIButton *)sender { 
    [self animateToPercentWayAround:sender.tag]; 
} 

这是子类的CAShapeLayer代码,

-(instancetype)initWithFrame:(CGRect) frame color:(CGColorRef) color lineWidth:(CGFloat) lineWidth { 
    if (self = [super init]) { 

     self.path = [UIBezierPath bezierPathWithOvalInRect:CGRectInset(frame, 1, 1)].CGPath; 
     self.fillColor = [UIColor clearColor].CGColor; 
     self.strokeColor = color; 
     self.lineWidth = lineWidth; 
     self.strokeStart = 0; 
     self.strokeEnd = 0; 
    } 
    return self; 
} 
+0

这是一个真棒解决方案,非常感谢你!表现层与这样一个不错的接触!你救了我几个小时的头痛。所以干净和容易实施:) – NKorotkov 2014-11-06 09:10:25