2009-11-19 11 views
15

Me estoy acercando a la animación principal y al dibujo empíricamente. Estoy tratando de animar una forma simple; la forma en cuestión está formada por 3 líneas más una curva bezier. También se dibuja una línea roja para mostrar los puntos de control de la curva.Animando una forma con CoreAnimation

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

Mi controlador principal se limita a añadir esta subvista y llama al método adjustWave siempre touchesEnd. Aquí está el código para mi clase de dibujo de formas. Como puede ver, la clase tiene una propiedad, cp1x (la x del punto de control 1 de bezier). Este es el valor que me gustaría animar. Cuidado, este es un intento tonto ...

- (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]; 
} 

La forma no cambia. Si, por el contrario, saco el código CA y agrego un simple `[self setNeedsDisplay] en el último método, la forma cambia, pero obviamente sin CA. ¿Puedes ayudar a sme? Estoy seguro de que estoy cometiendo un error muy básico aquí ... Gracias de antemano, Davide

+0

Como dice Brad, puede usar la clase CAShapeLayer para animar una forma arbitraria construyendo una CABasicAnimation o CAKeyframeAnimation y animando por la propiedad 'path'. Escribí una publicación sobre esta clase si quieres ver el código de muestra. http://bit.ly/shapelayer –

Respuesta

17

Si está escribiendo esto para iPhone OS 3.x (o Snow Leopard), el nuevo CAShapeLayer class debería permitirle hacer este tipo de animación con bastante facilidad. Si tiene una ruta que mantiene el mismo número de puntos de control (como en su caso), puede establecer esa ruta a CAShapeLayer y luego animar la propiedad de la ruta desde ese valor de inicio hasta su ruta final. Core Animation realizará la interpolación adecuada de los puntos de control en la ruta para animarlo entre esos dos estados (más, si usa CAKeyframeAnimation).

Tenga en cuenta que esta es una capa, por lo que deberá agregarla como una subcapa de su UIView. Además, no creo que la propiedad de ruta se anime implícitamente, por lo que puede necesitar crear manualmente una CABasicAnimation para animar el cambio de forma de la ruta 1 a la ruta 2.

EDITAR (21/11/2009): Joe Ricioppo tiene un buen artículo sobre CAShapeLayer here, que incluye algunos videos que muestran este tipo de animaciones.

+0

CAShapeLayer es muy defectuoso en iPhone OS 3.x – dontWatchMyProfile

+0

@mystify - ¿De qué manera? He tenido un trabajo razonablemente bueno para mí, pero debes recordar tener la misma cantidad de puntos de control inicial y final en tus rutas o los resultados no están definidos. –

-1

No podrá animar su forma con CA. Solo puede animar propiedades de capa en CA, no propiedades personalizadas.

CA puede ser rápido porque no tiene que volver a llamar a su código para realizar animaciones, si piensa en cómo se implementa, básicamente es solo un hilo que ejecuta operaciones de primitivas GL con marcos y contenidos CALayer.

Las animaciones de CA son conjuntos de instrucciones para que CA se ejecute en el hilo de fondo, disparar y olvidar (más devolución de llamada al finalizar la animación), no devoluciones de llamada a su código.

La animación del contenido de una capa requerirá que CA le devuelva la llamada para dibujar en cada cuadro o para que le indique a CA cómo dibujar. Ninguno de los dos sucede.

+0

Supongo que tengo mucho que aprender aquí :) En cualquier caso, realmente no me importa el código que he mostrado anteriormente, es solo una prueba de concepto. ¿Hay alguna forma alternativa de hacer algo similar con CA? ¿O debería dejar CA solo y llamar a setNeedDisplay? – nutsmuggler

+0

setNeedsDisplay es de una manera, OpenGL es otra. No creo que puedas con CA. – duncanwilcox

+1

Puedes animar formas usando la clase CAShapeLayer y animando la propiedad 'ruta'. –

Cuestiones relacionadas