2012-02-13 43 views
5

Tôi đang cố gắng áp dụng hiệu ứng chuyển động chậm cho ứng dụng của mình, khá giống như cách bạn có thể làm chậm hiệu ứng đồ họa nhất của Mac OS nếu bạn nhấn Shift.Làm chậm và tăng tốc hoạt ảnh bằng CoreAnimation

Ứng dụng của tôi sử dụng CoreAnimation, vì vậy tôi nghĩ nó không phải là biggie: đặt speed thành một số giá trị chậm hơn (như 0.1) và đặt lại thành 1 sau khi hoàn tất và tôi sẽ sử dụng.

Có vẻ như, thật không may, đây không phải là cách phù hợp. Sự suy giảm hoạt động rất tốt, tuy nhiên khi tôi muốn trở lại tốc độ bình thường, nó lại tiếp tục như thể tốc độ là 1 toàn bộ thời gian. Điều này về cơ bản có nghĩa là nếu tôi giữ Shift đủ lâu, ngay sau khi tôi phát hành nó, hoạt ảnh sẽ hoàn thành ngay lập tức.

Tôi đã tìm thấy trang QA kỹ thuật giải thích cách tạm dừng và tiếp tục hoạt ảnh nhưng tôi dường như không thể làm đúng nếu nó không hoàn toàn tạm dừng hoạt ảnh. Tôi chắc chắn không giỏi thời gian cong vênh.

Điều gì sẽ là đúng cách để làm chậm sau đó tiếp tục hoạt ảnh với CoreAnimation?

Dưới đây là đoạn code hữu ích:

-(void)flagsChanged:(NSEvent *)theEvent 
{ 
    CALayer* layer = self.layer; 
    [CATransaction begin]; 
    CATransaction.disableActions = YES; 
    layer.speed = (theEvent.modifierFlags & NSShiftKeyMask) ? 0.1 : 1; 
    [CATransaction commit]; 
} 
+1

thường giữ phím shift chỉ áp dụng cho hình ảnh động bắt đầu khi thay đổi được tổ chức, và buông bỏ nó không ngay lập tức tăng tốc độ hoạt hình. Điều này nói chung có thể được thực hiện chỉ đơn giản bằng cách làm cho thời lượng của hoạt ảnh phụ thuộc vào việc thay đổi được giữ lại tại thời điểm hoạt hình được tạo ra. –

+1

@Kevin Ballard, tôi biết; nhưng bên cạnh đó đó là một hiệu ứng tuyệt vời, nó cũng sẽ có thể được _useful_ trong bối cảnh của tôi để có thể làm chậm nó xuống bất cứ lúc nào. – zneak

+0

Vâng, tôi nghĩ khi bạn thay đổi tốc độ, bạn cũng sẽ phải tính toán thời gian bù đắp để áp dụng sao cho thời gian cũ * thời gian == báo chí * thời gian + bù đắp –

Trả lời

4

vấn đề Tricky ...

tôi thiết lập một thử nghiệm với một UIView cơ bản. Tôi bắt đầu một hoạt ảnh của lớp của nó từ điểm hiện tại của nó đến một điểm mục tiêu.

Để làm chậm hoạt ảnh chính, tôi thực sự phải tạo và thay thế một hoạt ảnh mới (vì bạn không thể sửa đổi hoạt ảnh hiện tại).

Điều đặc biệt quan trọng là tìm hiểu xem hoạt ảnh hiện tại đã diễn ra bao xa. Điều này được thực hiện bằng cách truy cập beginTime, currentTime, tính thời gian trôi qua và sau đó tìm ra thời lượng của hoạt ảnh mới trong bao lâu.

- (void)initiate { 
    if(!initiated) { 
     [CATransaction begin]; 
     [CATransaction disableActions]; 
     [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut]]; 
     CABasicAnimation *ba = [CABasicAnimation animationWithKeyPath:@"position"]; 
     ba.duration = 10.0f; 
     ba.fromValue = [NSValue valueWithCGPoint:view.layer.position]; 
     ba.toValue = [NSValue valueWithCGPoint:CGPointMake(384, 512)]; 
     [view.layer addAnimation:ba forKey:@"animatePosition"]; 
     [CATransaction commit]; 
     initiated = YES; 
    } 
} 

- (void)slow { 
    [CATransaction begin]; 
    CABasicAnimation *old = (CABasicAnimation *)[view.layer animationForKey:@"animatePosition"]; 
    CABasicAnimation *ba = [CABasicAnimation animationWithKeyPath:@"position"]; 
    CFTimeInterval animationBegin = old.beginTime; 
    CFTimeInterval currentTime = CACurrentMediaTime(); 
    CFTimeInterval elapsed = currentTime - animationBegin; 
    ba.duration = [[old valueForKey:@"duration"] floatValue] - elapsed; 
    ba.duration = [[old valueForKey:@"duration"] floatValue]; 
    ba.autoreverses = [[old valueForKey:@"autoreverses"] boolValue]; 
    ba.repeatCount = [[old valueForKey:@"repeatCount"] floatValue]; 
    ba.fromValue = [NSValue valueWithCGPoint:((CALayer *)[view.layer presentationLayer]).position]; 
    ba.toValue = [old valueForKey:@"toValue"]; 
    ba.speed = 0.1; 
    [view.layer addAnimation:ba forKey:@"animatePosition"]; 
    [CATransaction commit]; 
} 

- (void)normal { 
    [CATransaction begin]; 
    CABasicAnimation *old = (CABasicAnimation *)[view.layer animationForKey:@"animatePosition"]; 
    CABasicAnimation *ba = [CABasicAnimation animationWithKeyPath:@"position"]; 
    CFTimeInterval animationBegin = old.beginTime; 
    CFTimeInterval currentTime = CACurrentMediaTime(); 
    CFTimeInterval elapsed = currentTime - animationBegin; 
    ba.duration = [[old valueForKey:@"duration"] floatValue] - elapsed; 
    ba.autoreverses = [[old valueForKey:@"autoreverses"] boolValue]; 
    ba.repeatCount = [[old valueForKey:@"repeatCount"] floatValue]; 
    ba.fromValue = [NSValue valueWithCGPoint:((CALayer *)[view.layer presentationLayer]).position]; 
    ba.toValue = [old valueForKey:@"toValue"]; 
    ba.speed = 1; 
    [view.layer addAnimation:ba forKey:@"animatePosition"]; 
    [CATransaction commit]; 
} 

Lưu ý: Đoạn mã trên chỉ hoạt động trong 1 hướng, chứ không phải với hình ảnh động mà autoreverse ...

+1

Tôi đã đăng mã của mình. – zneak

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