2012-03-02 2 views
13

Я использовал CAKeyframeAnimations для анимации свойств слоя transform.rotation и transform.translation.x, но у меня возникли проблемы с анимацией свойства transform неявно. У меня есть слой, который должен анимироваться между двумя состояниями, и интерполяция по умолчанию CABasicAnimation полностью неверна и не соответствует пути, который я хочу. CAKeyframeAnimation на помощь, или так я думал. Любая попытка анимации transform с использованием CAKeyframeAnimation приводит к тому, что представление сразу же привязывается к окончательному преобразованию во время других анимаций. Если я удалю первую половину следующей функции и пусть мои «трансформирующие» события используют CABasicAnimation в нижней части, она оживляет просто отлично, хотя с неверно интерполированными преобразованиями на этом пути.Как я могу преобразовать CATransform3Ds с CAKeyframeAnimation?

Моего слой делегат осуществил следующее:

- (id <CAAction>) actionForLayer:(CALayer *)layer forKey:(NSString *)event 
{  
    if ([event isEqualToString:@"transform"]) 
    { 
     CGSize startSize = ((CALayer *)self.layer.presentationLayer).bounds.size; 
     CGSize endSize = self.layer.bounds.size; 

     CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:event]; 
     animation.duration = 0.25; 

     NSMutableArray *values = [NSMutableArray array]; 

     int stepCount = 10; 
     for (int i = 0; i < stepCount; i++) 
     { 
      CGFloat p = i/(float)(stepCount - 1); 
      CGSize size = [self interpolateBetweenSize:startSize andSize:endSize percentage:p]; 
      CATransform3D transform = [self transformForSize:size]; 
      [values addObject:[NSValue valueWithCATransform3D:transform]]; 
     } 

     animation.values = values; 
     return animation; 
    } 

    // All other animations use this basic animation 
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:event]; 
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 
    animation.removedOnCompletion = YES; 
    animation.fillMode = kCAFillModeForwards; 
    animation.duration = 0.25; 
    return animation; 
} 

Мое преобразование перевод следует повернуть, но я думаю, что группа анимация с отдельной ключевыми кадрами анимации анимации с помощью сдвига и поворот может привести к сумасшедшим город. Я подтвердил, что размер & transform верен для всех значений p, которые я прохожу, и p строго колеблется от 0 до 1.

Я попытался установить функцию синхронизации по умолчанию, я пробовал настройку массив временных функций, я опустил ключевые слова, я установил repeatCount из 0, removedOnCompletion = YES и fillMode forwards, и это не повлияло. Я не правильно создаю анимацию ключевого кадра трансформирования?

+1

Не могли бы вы уточнить точный эффект, который вы пытаетесь достичь? Вы описываете его как перевод, за которым следует ротация, но из вашего кода это выглядит так, что границы также оживляют - это правильно?Вы хотите, чтобы слой перемещался, а затем вращался, с границами, постоянно растущими или сжимающимися на обеих фазах анимации move/rotate? – GSnyder

+0

Почему это должно быть неявным? Этот код выглядит взломанным. Если вам нужен тонкий контроль, почему бы просто не создать анимацию и не добавить ее прямо к слою, о котором вы говорите, что у вас уже есть работа? Также просто верните 'nil' из этого метода делегата, если вы хотите, чтобы в них использовалась их анимация по умолчанию. –

ответ

0

Этот метод работал в iOS 3, но, похоже, был сломан в iOS 5.0.

5.1 «Волшебно» исправлено это, похоже, это ошибка в iOS 5.0. Я бы поставил радар, но теперь он работает в формате 5.1.

@ Gsnyder: Некоторое время: я экспериментирую с Clear-like UI (для чего-то совершенно не связанного с Clear) и придумал это: http://blog.massivehealth.com/post/18563684407/clear. Это должно объяснить необходимость поворота &.

С тех пор я создал переход затвора, который подразделяет представление на N слоев (вместо 2), которые выглядят так, если смотреть со стороны: /////.

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

@ Paul.s: Implicit позволяет мне сохранять эту абстракцию внутри самого класса слоев, не загрязняя контроллер представления, который им владеет. Контроллер вида должен просто изменять границы, и слой должен двигаться соответствующим образом. Я не поклонник контроллеров представлений, имеющих десятки пользовательских анимаций, когда сами представления могут справиться с этим.

Мне нужно использовать анимацию ключевого кадра, потому что анимация по умолчанию между слоями трансформируется/и _ анимируется с помощью неправильных углов, поэтому /// \ layers не выравниваются по всему преобразованию. Анимации ключевого кадра гарантируют правильное выравнивание краев, пока все они ожидают.

Я рассматриваю это закрытое, это, кажется, ошибка в iOS 5.0 и с тех пор исправлено. Всем спасибо.

0
(void)animateViewWith3DCurrentView:(UIView *)currentView withPoing:(CGPoint)movePoint 
{ 
    //flip the view by 180 degrees in its place first. 
    currentView.layer.transform =   CATransform3DRotate(currentView.layer.transform,myRotationAngle(180), 0, 1, 0); 

    //set the anchor point so that the view rotates on one of its sides. 
    currentView.layer.anchorPoint = CGPointMake(0.5, 0.5); 

    //Set up scaling 

    CABasicAnimation *resizeAnimation = [CABasicAnimation animationWithKeyPath:kResizeKey]; 

    //we are going to fill the screen here. So 423,337 
    [resizeAnimation setToValue:[NSValue valueWithCGSize:CGSizeMake(423, 337)]]; 
    resizeAnimation.fillMode   = kCAFillModeForwards; 
    resizeAnimation.removedOnCompletion = NO; 

    // Set up path movement 

    UIBezierPath *movePath = [UIBezierPath bezierPath]; 

    //the control point is now set to centre of the filled screen. Change this to make the path different. 
    // CGPoint ctlPoint  = CGPointMake(0.0, 0.5); 
    CGPoint ctlPoint  = CGPointMake(1024/2, 768/2); 

    //This is the starting point of the animation. This should ideally be a function of the frame of the view to be animated. Hardcoded here. 

    // Set here to get the accurate point.. 
    [movePath moveToPoint:movePoint]; 

    //The anchor point is going to end up here at the end of the animation. 
    [movePath addQuadCurveToPoint:CGPointMake(1024/2, 768/2) controlPoint:ctlPoint]; 

    CAKeyframeAnimation *moveAnim = [CAKeyframeAnimation animationWithKeyPath:kPathMovement]; 

    moveAnim.path    = movePath.CGPath; 
    moveAnim.removedOnCompletion = YES; 

    // Setup rotation animation 

    CABasicAnimation* rotateAnimation = [CABasicAnimation animationWithKeyPath:kRotation]; 
    //start from 180 degrees (done in 1st line) 
    CATransform3D fromTransform  = CATransform3DMakeRotation(myRotationAngle(180), 0, 1, 0); 
    //come back to 0 degrees 
    CATransform3D toTransform   = CATransform3DMakeRotation(myRotationAngle(0), 0, 1, 0); 

    //This is done to get some perspective. 
    CATransform3D persp1 = CATransform3DIdentity; 
    persp1.m34 = 1.0/-3000; 

    fromTransform = CATransform3DConcat(fromTransform, persp1); 
    toTransform = CATransform3DConcat(toTransform,persp1); 

    rotateAnimation.toValue    = [NSValue valueWithCATransform3D:toTransform]; 
    rotateAnimation.fromValue   = [NSValue valueWithCATransform3D:fromTransform]; 
    //rotateAnimation.duration   = 2; 
    rotateAnimation.fillMode   = kCAFillModeForwards; 
    rotateAnimation.removedOnCompletion = NO; 


    // Setup and add all animations to the group 

    CAAnimationGroup *group = [CAAnimationGroup animation]; 

    [group setAnimations:[NSArray arrayWithObjects:moveAnim,rotateAnimation, resizeAnimation, nil]]; 

    group.fillMode   = kCAFillModeForwards; 
    group.removedOnCompletion = NO; 
    group.duration   = 0.7f; 
    group.delegate   = self; 

    [group setValue:currentView forKey:kGroupAnimation]; 

    [currentView.layer addAnimation:group forKey:kLayerAnimation]; 
} 
Смежные вопросы