2014-01-15 2 views
0

В настоящее время у меня есть таймер, ниже которого анимируется круговая линия - линия обратного отсчета. Это оживляет в соответствии с количеством секунд, которое я перехожу на _percent.Пользовательская анимация таймера с использованием UIBezierPath

Я хотел бы иметь еще одно круговое колесо, которое отображает секунды. Однако я изо всех сил стараюсь, чтобы анимация продолжалась 1 секунда за каждую секунду, оставшуюся в _percent. например если процент равен 100, мне нужен круг, чтобы оживить цикл 100 раз, продолжающийся 1 секунду. (а также для достижения эффекта анимации, показанного ниже.

Вот чертеж для ясности :) Первая строка из 3 показывает, что это такое в настоящее время, а нижняя строка 3 показывает эффект, который я желаю ... enter image description here

Вот как я выпалить таймер на мой взгляд класса контроллера:

-(void)viewDidLoad 
{ 
     CPCircleCountdownView *m_testView; 
    m_testView.percent = 100; 
} 

- (IBAction)StartTimerButtonPressed:(id)sender 
{ 
    // Kick off a timer to count it down 
    m_timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(decrementSpin) userInfo:nil repeats:YES]; 
} 

- (void)decrementSpin 
{ 
    // If we can decrement our percentage, do so, and redraw the view 
    if (m_testView.percent > 0) { 
     m_testView.percent = m_testView.percent - 1; 
     [m_testView setNeedsDisplay]; 
    } 
    else { 
     [m_timer invalidate]; 
     m_timer = nil; 
    } 
} 

и вот мой CPCountdownView, где я хочу, чтобы добавить новую круговую анимацию продолжительностью в одну секунду для каждой второй слева. Обе теории в теории должны заканчиваться одновременно.

#import "CPCircleCountdownView.h" 

@interface CPCircleCountdownView() 
{ 
    CGFloat startAngle; 
    CGFloat endAngle; 
} 

@end 

@implementation CPCircleCountdownView 

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     // Initialization code 

     self.backgroundColor = [UIColor clearColor]; 

     //get start and end angles 
     startAngle = M_PI * 1.5; 
     endAngle = startAngle + (M_PI * 2); 
    } 
    return self; 
} 

- (void)drawRect:(CGRect)rect 
{ 
    //Display arc percent 
    //NSString *textContent = [NSString stringWithFormat:@"%d", self.percent]; //TODO: Pass total number of seconds int 

    //------------------------- 
    UIBezierPath* bezierPath = [UIBezierPath bezierPath]; 
    // Create our arc, with the correct angles 
    [bezierPath addArcWithCenter:CGPointMake(rect.size.width/2, rect.size.height/2) 
          radius:130 
         startAngle:startAngle 
         endAngle:(endAngle - startAngle) * (_percent/_overallScore) + startAngle 
         clockwise:YES]; 
    // Set the display for the path, and stroke it 
    bezierPath.lineWidth = 2; 
    [[UIColor colorWithRed:122.0/255.0 green:197.0/255.0 blue:205.0/255.0 alpha:1.0] setStroke]; 
    [bezierPath stroke]; 

    //------------------------- 
} 

Любая помощь будет здорово я относительно новый, так что если вы могли бы дать мне примеры, которые бы здорово :) Спасибо

ответ

0

, вероятно, лучше было бы использовать 2 CAShapeLayers и живой путь Безье , Предположим CPCircleCountdownView является UIView Подкласс

@interface CPCircleCountdownView() 

    @property (nonatomic) CAShapeLayer* layer1; 
    @property (nonatomic) CAShapeLayer* layer2; 
    @property (nonatomic, assign) float startAngle; 
    @property (nonatomic, assign) float endAngle;  
@end 

@implementation CPCircleCountdownView 

- (void)intiWithFrame:(CGRect) Frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     _startAngle = M_PI * 1.5; 
    _endAngle = _startAngle + (M_PI * 2); 

    } 


} 

-(void)layoutSubviews{ 

    self.layer1 = [CAShapeLayer layer]; 
    self.layer1.fillColor = [UIColor clearColor].CGColor; 
    self.layer1.strokeColor = [UIColor redColor].CGColor; 

    self.layer2 = [CAShapeLayer layer]; 
    self.layer2.fillColor = [UIColor clearColor].CGColor; 
    self.layer2.strokeColor = [UIColor greenColor].CGColor; 

    [self.layer1 setFrame:CGRectMake(50, 50, 200, 200)]; 
    [self.layer2 setFrame:CGRectMake(50, 50, 200, 200)]; 
    UIBezierPath *path1 = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.layer1.frame.size.width/2, self.layer1.frame.size.height/2) 
                radius:130 
               startAngle:self.startAngle 
                endAngle:self.endAngle 
                clockwise:YES]; 

    UIBezierPath *path2 = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.layer2.frame.size.width/2, self.layer2.frame.size.height/2) 
                radius:125 
               startAngle:self.endAngle 
                endAngle:self.startAngle 
                clockwise:NO]; 

    self.layer1.path = path1.CGPath; 
    self.layer2.path = path2.CGPath; 
    [self.view.layer addSublayer:self.layer1]; 
    [self.view.layer addSublayer:self.layer2]; 
    [self.layer1 setStrokeEnd:1.0f]; 
    [self.layer2 setStrokeEnd:0.0f]; 
    // i've placed this here for convenience in testing, really it should be in method called by your button Action 
    [self decrementSpinForValue:100]; 

} 

- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)finished { 
    [self.layer1 removeAllAnimations]; 
    [self.layer2 removeAllAnimations]; 
} 


-(void) decrementSpinForValue:(float) percent{ 

    CABasicAnimation *strokeEndAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; 
    strokeEndAnimation.delegate = self; 
    strokeEndAnimation.duration = percent; 
    [strokeEndAnimation setFillMode:kCAFillModeForwards]; 
    strokeEndAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; 
    strokeEndAnimation.removedOnCompletion = NO; 
    strokeEndAnimation.fromValue = [NSNumber numberWithFloat:1.0f]; 
    strokeEndAnimation.toValue = [NSNumber numberWithFloat:0.0f]; 
    [self.layer1 addAnimation:strokeEndAnimation forKey:@"progressOuterStatus"]; 

    CABasicAnimation *strokeEndAnimation2 = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; 
    strokeEndAnimation2.duration = 1.0f; 
    strokeEndAnimation2.repeatCount = percent; 
    [strokeEndAnimation2 setFillMode:kCAFillModeForwards]; 
    strokeEndAnimation2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; 
    strokeEndAnimation2.removedOnCompletion = NO; 
    strokeEndAnimation2.fromValue = [NSNumber numberWithFloat:0.0f]; 
    strokeEndAnimation2.toValue = [NSNumber numberWithFloat:1.0f]; 
    [self.layer2 addAnimation:strokeEndAnimation2 forKey:@"progressInnerStatus"]; 


} 

@end 

Я думаю, что дает представление о том, как вы можете сделать это.

+0

Проблема в том, что cabasicanimation удаляется, когда приложение закрывается и открывается снова. Усваивается больше анимации. – Ryan

+0

Достаточно просто, чтобы добавлять уведомления и воссоздавать анимацию, где последний остановился. – MDB983

Смежные вопросы