1

ПОДХОД 1Изменение CALayer цвета при анимации

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeStart"]; 
[CATransaction begin]; 
    { 
     [CATransaction setAnimationDuration:15];//Dynamic Duration 
     [CATransaction setCompletionBlock:^{ 

     }]; 

     animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; 
     animation.autoreverses = NO; 
     animation.removedOnCompletion = NO; 
     animation.fromValue = @0; 
     animation.toValue = @1; 
     animation.timeOffset = 0; 
     animation.fillMode = kCAFillModeForwards; 
     [self.pathLayer addAnimation:animation forKey:animationKey]; 

    } 
    [CATransaction commit]; 

Я добавил CAShapeLayer (pathLayer), на мой взгляд, и я хочу, чтобы оживить вокруг точки зрения с эффектом удара, приведенный выше код делает работу, но мой проблема заключается в изменении цвета в 3 равных пропорциях. Поэтому я предполагаю повторить вышеуказанный код 3 раза и изменить следующие строки в соответствующем порядке.

для 1-го

animation.fromValue = @0; 
    animation.toValue = @(1/3); 
    animation.timeOffset = 0; 

для 2-го

animation.fromValue = @(1/3); 
    animation.toValue = @(2/3); 
    animation.timeOffset = 0;// I don't know how to exactly set this active local 
time since the duration which is currently 15 is dynamic can be 30 or 10. 

для 3

animation.fromValue = @(2/3); 
    animation.toValue = @(3); 
    animation.timeOffset = 0;// Active local time- Not sure how and which value to set 

ПОДХОД 2

Вместо 3 транзакта ионы со смещением позволяют начать вторую транзакцию, когда 1-й закончен, а 3-й - 2-й. Но доля времени, затрачиваемого на запуск новой анимации при завершении лаг/рывок, видна.

ПОДХОД 3

SubClass CAShapeLayer

Поступая SubClass, метод drawInContext вызывается только один раз, и если добавить некоторые дополнительные свойства и он изменил метод drawInContext называется несколько раз, и таким образом цвет слоя можно изменить после определенного периода выполнения. Но переопределение метода drawInContext не служит цели.

Любые предложения? Я не хочу реализовывать NSTimer отдельно.

ответ

7

Я не на 100% понятен, что вы хотите здесь, но если цель заключается только в том, чтобы весь штрих изменил цвет, как он рисует, но на трех дискретных этапах, я бы предложил добавить следующее. Я приготовил эти примеры в шаблоне «Single View Application» по умолчанию. У меня есть кнопка, настроенная с ее действием, указывающая на -doStuff:. Если весь цвет обводки должны были измениться, это может выглядеть примерно так:

Whole stroke changes color

Для получения этого кода выглядел так:

@implementation MyViewController 
{ 
    CAShapeLayer* mLayer; 
} 

- (IBAction)doStuff:(id)sender 
{ 
    const NSUInteger numSegments = 3; 
    const CFTimeInterval duration = 2; 

    [mLayer removeFromSuperlayer]; 

    mLayer = [[CAShapeLayer alloc] init]; 
    mLayer.frame = CGRectInset(self.view.bounds, 100, 200); 
    mLayer.fillColor = [[UIColor purpleColor] CGColor]; 
    mLayer.lineWidth = 12.0; 
    mLayer.lineCap = kCALineCapSquare; 
    mLayer.strokeEnd = 0.0; 
    mLayer.path = [[UIBezierPath bezierPathWithRect: mLayer.bounds] CGPath]; // This can be whatever. 

    [self.view.layer addSublayer: mLayer]; 

    [CATransaction begin]; 
    { 
     [CATransaction setAnimationDuration: duration];// Dynamic Duration 
     [CATransaction setCompletionBlock:^{ NSLog(@"Done"); }]; 

     const double portion = 1.0/((double)numSegments); 
     NSMutableArray* values = [NSMutableArray arrayWithCapacity: numSegments]; 
     NSMutableArray* times = [NSMutableArray arrayWithCapacity: numSegments + 1]; 
     for (NSUInteger i = 0; i < numSegments; i++) 
     { 
      [values addObject: (__bridge id)[[UIColor colorWithHue: i * portion saturation:1 brightness:1 alpha:1] CGColor]]; 
      [times addObject: @(i * portion)]; 
     } 

     [times addObject: @(1.0)]; // Have to add this, otherwise the last value wont get used. 

     { 
      CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath: @"strokeColor"]; 
      animation.keyTimes = times; 
      animation.values = values; 
      animation.calculationMode = kCAAnimationDiscrete; 
      animation.removedOnCompletion = NO; 
      animation.timeOffset = 0; 
      animation.fillMode = kCAFillModeForwards; 
      [mLayer addAnimation: animation forKey: @"strokeColor"]; 
     } 
     { 
      CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath: @"strokeEnd"]; 
      animation.fromValue = @(0); 
      animation.toValue = @(1); 
      animation.removedOnCompletion = NO; 
      animation.timeOffset = 0; 
      animation.fillMode = kCAFillModeForwards; 
      [mLayer addAnimation: animation forKey: @"strokeEnd"]; 
     } 
    } 
    [CATransaction commit]; 
} 

@end 

С другой стороны, если цель состоит в том, чтобы иметь три разные сегменты штриха, все с разными цветами, это немного сложнее, но все равно можно сделать с теми же основными принципами. Следует отметить, что без пользовательского чертежа у вашего CAShapeLayer s не может быть больше одного цвета хода (AFAIK), поэтому вам нужно разбить его на несколько подслоев.

Этот следующий пример помещает слой фигуры в представление, а затем добавляет подуровни для каждой части штриха и устанавливает анимацию таким образом, что она появляется при рисовании одного, многоцветного штриха, где каждый сегмент является отдельный цвет.Вот примерно то, что это выглядело как:

Animated GIF of output

Вот код:

@implementation MyViewController 
{ 
    CAShapeLayer* mLayer; 
} 

- (IBAction)doStuff:(id)sender 
{ 
    const NSUInteger numSegments = 3; 
    const CFTimeInterval duration = 2; 

    [mLayer removeFromSuperlayer]; 

    mLayer = [[CAShapeLayer alloc] init]; 
    mLayer.frame = CGRectInset(self.view.bounds, 100, 200); 
    mLayer.fillColor = [[UIColor purpleColor] CGColor]; 
    mLayer.lineWidth = 12.0; 
    mLayer.lineCap = kCALineCapSquare; 
    mLayer.path = [[UIBezierPath bezierPathWithRect: mLayer.bounds] CGPath]; // This can be whatever. 

    [self.view.layer addSublayer: mLayer]; 

    [CATransaction begin]; 
    { 
     [CATransaction setAnimationDuration: duration];//Dynamic Duration 
     [CATransaction setCompletionBlock:^{ NSLog(@"Done"); }]; 

     const double portion = 1.0/((double)numSegments); 

     for (NSUInteger i = 0; i < numSegments; i++) 
     { 
      CAShapeLayer* strokePart = [[CAShapeLayer alloc] init]; 
      strokePart.fillColor = [[UIColor clearColor] CGColor]; 
      strokePart.frame = mLayer.bounds; 
      strokePart.path = mLayer.path; 
      strokePart.lineCap = mLayer.lineCap; 
      strokePart.lineWidth = mLayer.lineWidth; 

      // These could come from an array or whatever, this is just easy... 
      strokePart.strokeColor = [[UIColor colorWithHue: i * portion saturation:1 brightness:1 alpha:1] CGColor]; 
      strokePart.strokeStart = i * portion; 
      strokePart.strokeEnd = (i + 1) * portion; 

      [mLayer addSublayer: strokePart]; 

      CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath: @"strokeEnd"]; 
      NSArray* times = @[ @(0.0), // Note: This works because both the times and the stroke start/end are on scales of 0..1 
           @(strokePart.strokeStart), 
           @(strokePart.strokeEnd), 
           @(1.0) ]; 
      NSArray* values = @[ @(strokePart.strokeStart), 
           @(strokePart.strokeStart), 
           @(strokePart.strokeEnd), 
           @(strokePart.strokeEnd) ]; 

      animation.keyTimes = times; 
      animation.values = values; 
      animation.removedOnCompletion = NO; 
      animation.fillMode = kCAFillModeForwards; 
      [strokePart addAnimation: animation forKey: @"whatever"]; 
     } 
    } 
    [CATransaction commit]; 
} 

@end 

Я не уверен, что я точно понял, что вы собираетесь для, но, надеюсь, один из них является полезным ,

+0

спасибо за ответ, это абсолютно новая перспектива для меня, чтобы увидеть, как красиво мы можем играть с анимацией слоев. Я реализовал его, и единственное неправильное в моей реализации было на третьем шаге: animation.toValue = @ (3); который должен был быть animation.toValue = @ (1); как бы я хотел, чтобы вы, пожалуйста, добавили способ, которым вы внедрили ответ, который изменит цвет всего слоя на шаге 2, а затем цвет всего слоя на шаге 3. Спасибо – yunas

+1

@yunas отредактирован, чтобы дать более подробную информацию о «полном штрихе» меняется цвет ". – ipmcc

+0

@ipmcc Как мы можем изменить цвета штриха от одного к другому постепенно, почти как градиент, в этом примере? Благодарю. – Unheilig

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

  • Нет связанных вопросов^_^