2011-12-14 12 views
9

¿Cómo puedo hacer una escala animada circular pero mantener la posición central del círculo en el mismo punto. Este código hace que el centro del círculo se mueva hacia abajo y hacia la derecha, parece que está encuadernado en la esquina superior izquierda por el marco.Animar una escala en un círculo para mantener la posición central

Esta capa es como se puede ver una máscara en otra capa.

CGMutablePathRef path = CGPathCreateMutable(); 
CGPathAddEllipseInRect(path, nil, CGRectMake(400, 400, 1000, 1000)); 

CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] init]; 
[shapeLayer setPath:path]; 
[shapeLayer setFrame:[glView frame]]; 
[shapeLayer setFillColor:[[UIColor blackColor] CGColor]]; 

[[glView layer] setMask:shapeLayer]; 

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; 
animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.0, 0.0, 0)]; 
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)]; 
animation.repeatCount = 1; 
animation.removedOnCompletion = NO; 
animation.fillMode = kCAFillModeForwards; 
animation.duration = 3; 
[shapeLayer addAnimation:animation forKey:@"transform.scale"]; 

Respuesta

6

Una capa se escala alrededor de su punto de anclaje , que por defecto es el centro del marco de la capa. Esto se explica en Core Animation Programming Guide - Specifying a Layer's Geometry.

Su problema es que el centro de su círculo no está en el mismo punto que el punto de anclaje de su capa.

Así que una manera de solucionar el problema es mover shapeLayer.anchorPoint a ser el mismo que el centro del círculo, como esto:

CGRect circleFrame = CGRectMake(400, 400, 1000, 1000); 
CGPoint circleAnchor = CGPointMake(CGRectGetMidX(circleFrame)/CGRectGetMaxX(circleFrame), 
    CGRectGetMidY(circleFrame)/CGRectGetMaxY(circleFrame)); 
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:circleFrame]; 

CAShapeLayer *shapeLayer = [CAShapeLayer layer]; 
shapeLayer.path = path.CGPath; 
shapeLayer.anchorPoint = circleAnchor; 
shapeLayer.frame = glView.frame; 
shapeLayer.fillColor = [UIColor blackColor].CGColor; 

glView.layer.mask = shapeLayer; 
// and then your animation code 

Usted desea establecer el punto anclaje antes se establece el marco, porque establecer el punto de anclaje después de configurar el marco cambiará el marco.

+4

He intentado con diferentes puntos de anclaje, pero todavía no hay cambios. Siempre animando a la esquina izquierda. – Tariq

+0

Rob Mayoff es correcto. Observe cómo calcula el punto de anclaje en el espacio de coordenadas de la unidad, dividiendo el centro del cuadro por su máximo en cada dimensión. Entonces el punto de anclaje debe ser un valor de 0.0 a 1.0. – erikprice

+0

Quiero agregar que, en la mayoría de los casos, no desea cambiar 'anchorPoint' como aquí. Solo necesitas establecer el marco adecuado. Por ejemplo: desea crear una forma con una ruta y luego escalarla. Primero crea una forma en rect que tenga origen 'x: 0, y: 0'. Luego, después de establecer esta ruta en su 'CAShapeLayer', necesita diseñar su capa estableciendo frame. Establezca el marco como lo necesita, por ejemplo, como en esta pregunta 'CGRectMake (400, 400, 1000, 1000)'. Ahora su escala será desde el punto x, y = 400 + 1000/2 = 900 –

1

Estos son conjeturas, no es capaz de probar a mí mismo en este momento: Marco de

  • Conjunto shapeLayer a glView de bounds, no frame como debe ser en el sistema de coordenadas del punto de vista al que pertenece, no la supervista
  • Establezca shapeLayer anchorPoint en 0.5,0.5 - este es el valor predeterminado para un CALayer (es decir, el centro de la capa) pero a partir de lo que está describiendo no es el caso para su capa de forma, a menos que el elemento frame/bounds esté causando la cuestión.
Cuestiones relacionadas