2013-05-08 31 views
14

Cố gắng làm hoạt hình một hình elip đeo mặt nạ trên một UIView được quy mô chuyển đổi còn lại ở vị trí trung tâm.CABasicAnimation - quy mô biến đổi giữ ở trung tâm

Tôi đã tìm thấy CALayer - CABasicAnimation not scaling around center/anchorPoint, và sau đó bằng cách thêm một tài sản bounds đến maskLayerCAShapeLayer Tuy nhiên, điều này kết thúc với mặt nạ được vị trí ở góc trái với chỉ 1/4 của nó hiển thị. Tôi muốn mặt nạ ở lại giữa màn hình.

@synthesize maskedView; 
- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    UIViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"Next"]; 

    vc.view.frame = CGRectMake(0,0, self.view.frame.size.width, self.view.frame.size.height); 
vc.view.layer.bounds = self.view.layer.bounds; 

    CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init]; 

    CGRect maskRect = CGRectMake((self.view.frame.size.width/2)-50, (self.view.frame.size.height/2)-50, 100, 100); 
    CGMutablePathRef path = CGPathCreateMutable(); 
    CGPathAddEllipseInRect(path, nil, maskRect); 
    [maskLayer setPath:path]; 

    CGPathRelease(path); 

    vc.view.layer.mask = maskLayer; 
    [self.view addSubview:vc.view]; 

    maskedView = vc.view; 
    [self startAnimation]; 
} 

Animation ...

-(void)startAnimation 
{ 
    maskedView.layer.mask.bounds = CGRectMake((self.view.frame.size.width/2)-50, (self.view.frame.size.height/2)-50, 100, 100); 
    maskedView.layer.mask.anchorPoint = CGPointMake(.5,.5); 
    maskedView.layer.mask.contentsGravity = @"center"; 

    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; 

    animation.duration = 1.0f; 
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 
    animation.fromValue = [NSNumber numberWithFloat:1.0f]; 
    animation.toValue = [NSNumber numberWithFloat:5.0f]; 

    [maskedView.layer.mask addAnimation:animation forKey:@"animateMask"]; 
} 

Cập nhật

tôi dường như đã cố định này với một hình ảnh động thứ hai trên phím position. Đây có phải là chính xác hoặc là có một cách tốt hơn để làm điều này?

CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath:@"position"]; 

animation2.duration = 1.0f; 

animation2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 

animation2.fromValue = [NSValue valueWithCGPoint:CGPointMake((self.view.frame.size.width/2), (self.view.frame.size.height/2))]; 
animation2.toValue = [NSValue valueWithCGPoint:CGPointMake((self.view.frame.size.width/2), (self.view.frame.size.height/2))]; 

[toBeMask.layer.mask addAnimation:animation2 forKey:@"animateMask2"]; 

Trả lời

6

Tôi dường như đã sửa lỗi này bằng hoạt ảnh thứ hai trên khóa vị trí. Đây có phải là chính xác hoặc là có một cách tốt hơn để làm điều này?

CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath:@"position"]; 

animation2.duration = 1.0f; 

animation2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 

animation2.fromValue = [NSValue valueWithCGPoint:CGPointMake((self.view.frame.size.width/2), (self.view.frame.size.height/2))]; 
animation2.toValue = [NSValue valueWithCGPoint:CGPointMake((self.view.frame.size.width/2), (self.view.frame.size.height/2))]; 

[toBeMask.layer.mask addAnimation:animation2 forKey:@"animateMask2"]; 
12

Bạn có thể tạo một quy mô xung quanh trung tâm của đối tượng thay vì (0, 0) như thế này:

CABasicAnimation *scale = [CABasicAnimation animationWithKeyPath:@"transform"]; 
CATransform3D tr = CATransform3DIdentity; 
tr = CATransform3DTranslate(tr, self.bounds.size.width/2, self.bounds.size.height/2, 0); 
tr = CATransform3DScale(tr, 3, 3, 1); 
tr = CATransform3DTranslate(tr, -self.bounds.size.width/2, -self.bounds.size.height/2, 0); 
scale.toValue = [NSValue valueWithCATransform3D:tr]; 

Vì vậy, chúng tôi bắt đầu với các "bản sắc" chuyển hóa (có nghĩa là 'không biến đổi'). Sau đó, chúng tôi dịch (di chuyển) đến trung tâm của đối tượng. Sau đó, chúng tôi mở rộng quy mô. Sau đó, chúng tôi di chuyển trở lại origo vì vậy chúng tôi trở lại nơi chúng tôi bắt đầu (chúng tôi chỉ muốn ảnh hưởng đến hoạt động quy mô).

+0

Không phải việc mở rộng quy mô ảnh hưởng đến bản dịch bạn làm sau nó? Tôi đang thử nghiệm này (cũng như với biến đổi affine bình thường) và quan điểm luôn luôn kết thúc trên cùng bên trái từ vị trí ban đầu của nó. – Ixx

+0

Điều này đã được làm việc trong trường hợp của tôi 'CABasicAnimation * scale = [CABasicĐộng vật sinh độngWithKeyPath: @" transform "]; CATransform3D tr = CATransform3DIdentity; tr = CATransform3DScale (tr, 3, 3, 1); scale.toValue = [Giá trị NSValueWithCATransform3D: tr]; ' –

4

Tôi không chắc chắn lý do tại sao, nhưng CAShapeLayer không đặt thuộc tính giới hạn cho lớp. Trong trường hợp của tôi, đó là vấn đề. Thử đặt các giới hạn. Cần làm việc.

tôi đã làm một cái gì đó như thế này để xây dựng vòng tròn ban đầu

self.circle = [CAShapeLayer layer]; 
CGRect roundedRect = CGRectMake(0, 0, width, width); 
self.circle.bounds = roundedRect; 
UIBezierPath *start = [UIBezierPath bezierPathWithRoundedRect:roundedRect cornerRadius:width/2]; 
[self.circle setPath:start.CGPath]; 
self.circle.position = CGPointMake(whatever suits you); 
self.circleView.layer.mask = self.circle; 
[self.circleView.layer.mask setValue: @(1) forKeyPath: @"transform.scale"]; 

Và một cái gì đó như thế này để mở rộng nó

CABasicAnimation *scale = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; 
scale.fromValue = [self.circleView.layer.mask valueForKeyPath:@"transform.scale"]; 
scale.toValue = @(100); 
scale.duration = 1.0; 
scale.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 
[self.circleView.layer.mask setValue:scale.toValue forKeyPath:scale.keyPath]; 
[self.circleView.layer.mask addAnimation:scale forKey:scale.keyPath]; 

PD: AnchorPoint là theo mặc định (.5 ,. 5) theo tài liệu của Apple ... nhưng tất cả chúng ta đều biết điều đó không có nghĩa gì?

Hy vọng điều đó sẽ hữu ích !!

3

Tôi đã viết chức năng sau đây với nhiều chỉnh sửa và tùy chọn bổ sung, có thể hữu ích cho nhiều người khác.

func layerScaleAnimation(layer: CALayer, duration: CFTimeInterval, fromValue: CGFloat, toValue: CGFloat) { 
    let timing = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn) 
    let scaleAnimation: CABasicAnimation = CABasicAnimation(keyPath: "transform.scale") 

    CATransaction.begin() 
    CATransaction.setAnimationTimingFunction(timing) 
    scaleAnimation.duration = duration 
    scaleAnimation.fromValue = fromValue 
    scaleAnimation.toValue = toValue 
    layer.add(scaleAnimation, forKey: "scale") 
    CATransaction.commit() 
} 

Lưu ý: Đừng quên cập nhật kích thước sau khi hoàn thành phim hoạt hình, vì CATransaction quay ngược lại cung kích thước thực tế.

+0

scrubber? ,.,./,. –

+0

scrubber đoán được cho là lớp? anywas. đã giúp tôi khá tốt. cảm ơn bạn>) –

+1

@DavidSeek có lớp của nó không scrubber, tôi đã cập nhật nhờ câu trả lời của tôi. – Aamir

Các vấn đề liên quan