2014-11-05 140 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