2010-11-25 13 views
12

Tengo dos círculos que se mueven por la pantalla. Los círculos son ambos UIViews que contienen otras UIViews. El área fuera de cada círculo es transparente.Seguimiento de una animación de núcleo Animación

He escrito una función para crear un CGPath que conecta los dos círculos con forma de cuadrilátero. Lleno este camino en un CALayer transparente que abarca toda la pantalla. Como la capa está detrás de las dos vistas UIView circulares, parece conectarlas.

Finalmente, las dos UIViews están animadas usando Core Animation. La posición y el tamaño de ambos círculos cambian durante esta animación.

Hasta ahora, el único método que he tenido ningún éxito con es interrumpir la animación a intervalos regulares utilizando un NSTimer, a continuación, volver a calcular y trazar el haz basado en la ubicación de la capa de presentación del círculo. Sin embargo, el cuadrilátero va a la zaga de los círculos cuando la animación se acelera.

¿Hay alguna forma mejor de lograr esto usando Core Animation? ¿O debería evitar Core Animation e implementar mi propia animación usando un NSTimer?

Respuesta

12

Me enfrenté a un problema similar. Usé capas en lugar de vistas para la animación. Podrías probar algo como esto.

  1. Dibuja cada elemento como un CALayer e inclúyelos como subcapas para la capa de tu contenedor UIVIew. Los UIView son más fáciles de animar, pero tendrá menos control. Tenga en cuenta que para cualquier vista puede obtener su capa con [ver capa];
  2. Crea una subcapa personalizada para tu cuadrilátero. Esta capa debe tener una propiedad o varias propiedades que desee animar para esta capa. Llamemos a esta propiedad "customprop". Debido a que es una capa personalizada, desea volver a dibujar en cada fotograma de la animación. Para las propiedades que planea animar, su clase de capa personalizada debe devolver SÍ needsDisplayForKey :. De esta manera, se asegura de que - (void) drawInContext: (CGContextRef) theContext se invoque en cada cuadro.
  3. Coloque todas las animaciones (tanto círculos como cuadrículas) en la misma transacción;

Para los círculos es probable que pueda utilizar CALayers y establecer el contenido, si se trata de una imagen, la forma estándar:

layer.contents = [UIImage imageNamed:@"circle_image.png"].CGImage; 

Ahora, para la capa cuádruple, subclase CALayer y poner en práctica de esta manera:

- (void)drawInContext:(CGContextRef)theContext{ 
    //Custom draw code here 
} 
+ (BOOL)needsDisplayForKey:(NSString *)key{ 
    if ([key isEqualToString:@"customprop"]) 
     return YES; 
    return [super needsDisplayForKey:key]; 
} 

La transacción se vería así:

[CATransaction begin]; 
CABasicAnimation *theAnimation=[CABasicAnimation animationWithKeyPath:@"customprop"]; 

theAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(1000, 1000)]; 
theAnimation.duration=1.0; 
theAnimation.repeatCount=4; 
theAnimation.autoreverses=YES; 
theAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; 
theAnimation.delegate = self; 
[lay addAnimation:theAnimation forKey:@"selecting"]; 

[CATransaction setValue:[NSNumber numberWithFloat:10.0f] 
        forKey:kCATransactionAnimationDuration]; 
circ1.position=CGPointMake(1000, 1000); 
circ2.position=CGPointMake(1000, 1000); 
[CATransaction commit]; 

Ahora todas las rutinas sorteo ocurrir al mismo tiempo. Asegúrese de que su implementación de drawInContext: sea rápida. De lo contrario, la animación se retrasará.

Después de añadir cada subcapa de la capa de la UIViews, rememeber llamar [capa setNeedsDisplay]. No se llama automáticamente.

Sé que esto es un poco complicado. Sin embargo, las animaciones resultantes son mejores que usar un NSTimer y volver a dibujar en cada llamada.

+0

Solo una nota para aquellos que optan por implementar animación totalmente programática en lugar de usar propiedades personalizadas: no use 'NSTimer' para eso; sería lento y codicioso para la CPU. Para cualquier cosa relacionada con la animación, use ['CADisplayLink'] (https://developer.apple.com/library/ios/documentation/QuartzCore/Reference/CADisplayLink_ClassRef/), que se sincroniza con la frecuencia de actualización de la pantalla y es utilizado internamente por CoreAnimation . – skozin

1

Si necesita encontrar el estado visible actual de las capas, puede llamar al -presentationLayer en el CALayer en cuestión, y esto le dará una capa que se aproxima al utilizado para la representación. Tenga en cuenta que dije aproximaciones: no está garantizado que sea completamente preciso. Sin embargo, puede ser lo suficientemente bueno para sus propósitos.

+0

Como mencioné, ya he intentado usar la presentationLayer, pero va a la zaga de los círculos. Necesito un método más confiable para sincronizar la animación de múltiples componentes. – titaniumdecoy

+0

La única forma confiable en que puedo pensar es vincularme a la maquinaria de animación. Podría considerar usar un CAShapeLayer y animar su ruta en sincronización con los círculos. –

Cuestiones relacionadas