Анимация формы с помощью CoreAnimation

Я подхожу к основной анимации и рисованию опытным путем. Я пытаюсь оживить простую фигуру; рассматриваемая форма образована 3 линиями плюс кривая Безье. Также нарисована красная линия, чтобы показать контрольные точки кривой.

http://img.skitch.com/20091119-1ufar435jdq7nwh8pid5cb6kmm.jpg

Мой основной контроллер просто добавляет это подпредставление и вызывает метод adjustWave всякий раз, когда touchesEnd. Вот код для моего класса рисования фигур. Как видите, у класса есть одно свойство, cp1x (x контрольной точки Безье 1). Это значение, которое я хотел бы оживить. Учти, это тупая попытка ...

- (void)drawRect:(CGRect)rect {
    float cp1y = 230.0f;
    float cp2x = 100.0f;
    float cp2y = 120.0f;

    CGContextRef ctx = UIGraphicsGetCurrentContext(); 
    CGContextClearRect(ctx, rect);

    CGMutablePathRef path = CGPathCreateMutable(); 
    CGPathMoveToPoint(path, NULL, 10.0f, 200.0f); 
    CGPathAddCurveToPoint (path, NULL, cp1x, cp1y, cp2x, cp2y, 300.0f, 200.0f);
    CGPathAddLineToPoint(path, NULL, 300.0f, 300.0f); 
    CGPathAddLineToPoint(path, NULL, 10.0f, 300.0f); 
    CGPathCloseSubpath(path); 
    CGContextSetFillColorWithColor(ctx, [UIColor blueColor].CGColor); 
    CGContextAddPath(ctx, path); 
    CGContextFillPath(ctx);

    // Drawing a line from control points 1 and 2
    CGContextBeginPath(ctx);
    CGContextSetRGBStrokeColor(ctx,1,0,0,1);
    CGMutablePathRef cp1 = CGPathCreateMutable(); 
    CGPathMoveToPoint(cp1, NULL, cp1x, cp1y); 
    CGPathAddLineToPoint(cp1, NULL, cp2x, cp2y); 
    CGPathCloseSubpath(cp1); 
    CGContextAddPath(ctx, cp1); 
    CGContextStrokePath(ctx);
}

- (void)adjustWave {
    [UIView beginAnimations:@"movement" context:nil]; 
    [UIView setAnimationDelegate:self]; 
    [UIView setAnimationWillStartSelector:@selector(didStart:context:)]; 
    [UIView setAnimationDidStopSelector:@selector(didStop:finished:context:)]; 
    [UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
    [UIView setAnimationDuration:3.0f]; 
    [UIView setAnimationRepeatCount:3]; 
    [UIView setAnimationRepeatAutoreverses:YES]; 
    cp1x = cp1x + 20.0f;
    [UIView commitAnimations];
}

Форма не меняется. Если, наоборот, я извлеку код CA и добавлю простой `[self setNeedsDisplay] в последнем методе, форма изменится, но, очевидно, без CA. Вы можете помочь нам? Я уверен, что совершаю здесь очень серьезную ошибку ... Заранее спасибо, Давиде.


person nutsmuggler    schedule 19.11.2009    source источник
comment
Как говорит Брэд, вы можете использовать класс CAShapeLayer для анимации произвольной формы путем создания CABasicAnimation или CAKeyframeAnimation и анимации с помощью свойства path. Я написал сообщение об этом классе, если вы хотите ознакомиться с примером кода. bit.ly/shapelayer   -  person Joe Ricioppo    schedule 21.11.2009


Ответы (2)


Если вы пишете это для iPhone OS 3.x (или Snow Leopard), новый Класс CAShapeLayer должен позволить вам довольно легко выполнять такую ​​анимацию. Если у вас есть путь, который поддерживает такое же количество контрольных точек (как в вашем случае), вы можете установить этот путь на CAShapeLayer, а затем анимировать свойство пути от этого начального значения до конечного пути. Core Animation выполнит соответствующую интерполяцию контрольных точек на пути, чтобы оживить его между этими двумя состояниями (более того, если вы используете CAKeyframeAnimation).

Обратите внимание, что это слой, поэтому вам нужно будет добавить его в качестве подслоя вашего UIView. Кроме того, я не верю, что свойство path неявно анимирует, поэтому вам может потребоваться вручную создать CABasicAnimation, чтобы анимировать изменение формы от пути 1 к пути 2.

РЕДАКТИРОВАТЬ (21.11.2009): у Джо Ричоппо есть хорошая запись о CAShapeLayer здесь, включая несколько видеороликов, демонстрирующих такие виды анимации.

person Brad Larson    schedule 21.11.2009
comment
CAShapeLayer очень глючит в iPhone OS 3.x - person dontWatchMyProfile; 22.05.2010
comment
@mystify - Каким образом? У меня это работало достаточно хорошо, но вам нужно помнить, что на ваших путях должно быть одинаковое количество начальных и конечных контрольных точек, иначе результаты будут неопределенными. - person Brad Larson; 23.05.2010

Вы не сможете анимировать свою фигуру с помощью CA. В CA можно анимировать только свойства слоя, но не настраиваемые свойства.

CA может быть быстрым, потому что ему не нужно возвращаться к вашему коду для выполнения анимации, если вы думаете о том, как он реализован, это в основном просто поток, выполняющий операции примитивов GL с кадрами и содержимым CALayer.

CA-анимации - это наборы инструкций для CA для запуска в фоновом потоке, запуска и забывания (плюс обратный вызов при завершении анимации), а не обратных вызовов для вашего кода.

Анимация содержимого слоя потребовала бы, чтобы CA перезванивал вам для рисования в каждом кадре или позволял вам проинструктировать CA о том, как рисовать. Ничего из этого не происходит.

person duncanwilcox    schedule 20.11.2009
comment
Думаю, мне здесь есть чему поучиться :) Во всяком случае, меня особо не волнует код, который я показал выше, это просто доказательство концепции. Есть ли альтернативный способ сделать что-то подобное с CA? Или мне просто оставить CA и вызвать setNeedDisplay? - person nutsmuggler; 20.11.2009
comment
setNeedsDisplay - это один способ, openGL - другой. Я не верю, что у вас получится с CA. - person duncanwilcox; 20.11.2009
comment
Фактически вы можете анимировать фигуры с помощью класса CAShapeLayer и анимации свойства path. - person Joe Ricioppo; 21.11.2009
comment
У Джо действительно есть хорошая запись (с видео) о CAShapeLayer: tumbljack.com / post / 179975074 / - person Brad Larson; 22.11.2009
comment
Анимация пути, вероятно, решила бы конкретное изображение выше, хотя nutmuggler сказал, что приведенный выше код [является] просто доказательством концепции. Анимация пути ни в коем случае не относится к рисованию общего назначения. Но я не упомянул CAShapeLayer, извините за это. - person duncanwilcox; 22.11.2009