Невозможно объединить CAKeyframeAnimations для масштабирования и перевода

Я хотел бы одновременно выполнить масштабирование и перевод преобразования слоя, но работает только анимация перевода. Вот ошибочный код...

Здесь я создаю анимацию масштабирования с ключевым путем к scale.y:

    self.mainImage.layer.anchorPoint = CGPointMake(0.5, 1);
    CAKeyframeAnimation *mainAnimationScale = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale.y"];
    mainAnimationScale.duration             = 0.75;
    mainAnimationScale.repeatCount          = 0;
    mainAnimationScale.removedOnCompletion  = YES;
    mainAnimationScale.autoreverses         = NO;
    mainAnimationScale.fillMode             = kCAFillModeForwards;
    mainAnimationScale.values               = [NSArray arrayWithObjects:
                                          [NSNumber numberWithFloat:1.0],
                                          [NSNumber numberWithFloat:1.0],
                                          [NSNumber numberWithFloat:0.7],
                                          [NSNumber numberWithFloat:1.0],
                                          [NSNumber numberWithFloat:0.85],
                                          [NSNumber numberWithFloat:1.0],
                                           nil];
    mainAnimationScale.keyTimes             = [NSArray arrayWithObjects:
                                          [NSNumber numberWithFloat:0],
                                          [NSNumber numberWithFloat:0.65],
                                          [NSNumber numberWithFloat:0.72],
                                          [NSNumber numberWithFloat:0.84],
                                          [NSNumber numberWithFloat:0.91],
                                          [NSNumber numberWithFloat:1],
                                           nil];

Здесь я создаю анимацию перевода с указанием пути к translation.y:

    CAKeyframeAnimation *mainAnimationTrans = [CAKeyframeAnimation animationWithKeyPath:@"transform.translation.y"];
    mainAnimationTrans.duration             = 0.75;
    mainAnimationTrans.repeatCount          = 0;
    mainAnimationTrans.removedOnCompletion  = YES;
    mainAnimationTrans.autoreverses         = NO;
    mainAnimationTrans.fillMode             = kCAFillModeForwards;
    mainAnimationTrans.values               = [NSArray arrayWithObjects:
                                         [NSNumber numberWithFloat:-250.0],
                                         [NSNumber numberWithFloat:-250.0],
                                         [NSNumber numberWithFloat:0],
                                           nil];
    mainAnimationTrans.keyTimes             = [NSArray arrayWithObjects:
                                          [NSNumber numberWithFloat:0],
                                          [NSNumber numberWithFloat:0.65],
                                          [NSNumber numberWithFloat:1],
                                           nil];

Здесь я группирую их вместе и применяю к слою UIView:

    CAAnimationGroup *theGroup = [CAAnimationGroup animation];
    theGroup.duration = 0.75;
    theGroup.repeatCount = 0;
    theGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
    theGroup.animations = [NSArray arrayWithObjects:mainAnimationTrans, mainAnimationScale, nil];
    [self.mainImage.layer addAnimation:theGroup forKey:@"layerAnimation"];

Сначала я пытался добавить анимацию прямо в слой, но это тоже не сработало:

    [self.mainImage.layer addAnimation:mainAnimationTrans forKey:@"transform.scale.y"];
    [self.mainImage.layer addAnimation:mainAnimationTrans forKey:@"transform.translation.y"];

Я пробовал каждую строку, которую только мог придумать для значений keyPath, и я предполагаю, что это как-то связано с тем фактом, что я анимирую два аспекта преобразования, но я думал, что использование группы исправит это. Увы...


person leebert    schedule 24.05.2012    source источник


Ответы (2)


Ключом к выполнению этой работы является объединение преобразований. Я не знаю, почему я не понял этого раньше, так как это базовая математика Матрицы ... Я думаю, что мой коллега даже упомянул об этом вчера. Подтвердить

Во всяком случае, анимация, которую я собирался создать, заключалась в том, чтобы предмет выпадал и подпрыгивал, как только он достигал места назначения. Вот код:

    self.mainImage.layer.anchorPoint = CGPointMake(0.3, 1.0);
    CAKeyframeAnimation *mainImageAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
    mainImageAnimation.duration             = 0.75;
    mainImageAnimation.repeatCount          = 0;
    mainImageAnimation.removedOnCompletion  = NO;
    mainImageAnimation.autoreverses         = NO;
    mainImageAnimation.fillMode             = kCAFillModeForwards;
    mainImageAnimation.values               = [NSArray arrayWithObjects:
                                         [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DMakeTranslation(-8, -250, 0), 1, 1, 1)],
                                         [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DMakeTranslation(-8, 17, 0), 1, 1, 1)],
                                         [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DMakeTranslation(-8, 17, 0), 1.2, .8, 1)],
                                         [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DMakeTranslation(-8, 17, 0), .85, 1.15, 1)],
                                         [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DMakeTranslation(-8, 17, 0), 1.1, .9, 1)],
                                         [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DMakeTranslation(-8, 17, 0), 1, 1, 1)],
                                           nil];
    mainImageAnimation.keyTimes             = [NSArray arrayWithObjects:
                                          [NSNumber numberWithFloat:0],
                                          [NSNumber numberWithFloat:0.6],
                                          [NSNumber numberWithFloat:0.65],
                                          [NSNumber numberWithFloat:0.78],
                                          [NSNumber numberWithFloat:0.88],
                                          [NSNumber numberWithFloat:1],
                                           nil];
    mainImageAnimation.timingFunctions      = [NSArray arrayWithObjects:
                                         [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear],
                                         [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear],
                                         [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear],
                                         [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear],
                                         [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear],
                                         [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear],
                                           nil];
    [self.mainImage.layer addAnimation:mainImageAnimation forKey:@"transform"];

Что следует отметить:

  • Чтобы применить несколько свойств преобразования, объедините отдельные преобразования, передав результаты функции CATransform3DMakeXXX в аргумент преобразования функции CATransform3DXXX.
  • В матричной математике важен порядок преобразований: то, что вы передадите в матрицу последним, будет применено первым. В моем случае я хочу, чтобы перевод применялся до масштабирования, поэтому сначала мне нужно создать преобразование масштаба и применить его к последующему преобразованию перевода.
  • Изменение anchorPoint слоя изменяет положение слоя. В моем случае мне нужно было, чтобы опорная точка была асимметричной, и вы можете видеть, как я объясняю это изменение положения в трансформационном преобразовании: это место покоя не 0,0, а -8,17.

Надеюсь это поможет!

person leebert    schedule 25.05.2012

В отличие от вопроса, но связанного с этим, я пытался объединить два CAKeyFrameAnimations, вращение и масштабирование.

CAKeyframeAnimation *wiggle = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];
wiggle.values   = @[ @0.0, @-0.15, @0.0, @0.15, @-0.15, @0.0];
wiggle.keyTimes = @[ @0.0, @0.2,  @0.4, @0.6, @0.8,  @1.0];
wiggle.duration = 0.5;

CAKeyframeAnimation *resize = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
resize.duration = 0.5;
resize.values = @[@1.0, @1.5, @1.0];
resize.keyTimes = @[@0.0, @0.5, @1.0];

Добавление анимации по отдельности не работало, так как происходило только вращение.

[self.layer addAnimation:wiggle forKey:kAnimationKey];
[self.layer addAnimation:resize forKey:kAnimationKey];

Но это сработало, когда я создал группу анимации, содержащую обе CAKeyFrameAnimations.

CAAnimationGroup *animGroup = [[CAAnimationGroup alloc] init];
animGroup.animations = @[wiggle, resize];
animGroup.duration = 0.5;

[self.layer addAnimation:animGroup forKey:kAnimationKey];
person stevethomp    schedule 12.05.2014