2015-04-29 15 views
7

Tôi đang sử dụng CADisplayLink để thực hiện hoạt ảnh xem chỉ nội suy giá trị và vẽ lại chính chế độ xem đó.animate một UIView sử dụng CADisplayLink 'kết hợp' với CAMediaTimingFunction. (để có được đường cong tùy ý)

ví dụ: Tôi có một cái nhìn MyView và nó có một tài sản value, bất cứ khi nào giá trị được đặt tôi gọi là setNeedsDisplay và chế độ xem biết nội dung cần vẽ.

để tạo hiệu ứng này, tôi sử dụng CADisplayLink và tôi muốn chế độ xem 'biến đổi' giữa các giá trị. Tôi làm điều này bằng cách chỉ cần nội suy giá trị từ những hình ảnh động khởi động và dừng Value:

- (CGFloat)interpolatedValue:(CGFloat)sourceValue withValue:(CGFloat)targetValue forProgress:(CGFloat)progress;

bây giờ nhận được một tiến bộ tuyến tính rất dễ dàng và nhận được một 'đường cong cụ thể' (ok) nhưng tôi muốn để có thể đưa lợi thế của CAMediaTimingFunction để thực hiện việc này (hoặc một số logic có từ trước khác - Tôi không muốn phát minh lại bánh xe lần nữa ':)

+0

tại sao sử dụng CADisplayLink? nó chỉ là một bộ đếm thời gian. Và CAMediaTimingFunction chỉ lưu trữ một số khóa chính của đường cong. chính nó không làm đường cong. nếu tất cả những gì bạn muốn là một thuộc tính tùy chỉnh nhận được sự hỗ trợ đầy đủ của Core Animation, giống như một thuộc tính có khả năng hoạt hình tiêu chuẩn, bạn nên kế thừa CALayer. xem 'Thêm thuộc tính tùy chỉnh cho một lớp' trong tài liệu Xcode. – SolaWing

Trả lời

3

Có ích này RSTiming có thể hữu ích trong trường hợp của bạn. Bạn có thể xác định hàm thời gian bằng cách sử dụng hàm CAMediaTimingFunction tiêu chuẩn hoặc thậm chí xác định các hàm tùy chỉnh sử dụng 2 điểm điều khiển để xác định đường cong bezier.

Nếu tôi đã thiết lập của bạn, bạn có thể có một cái gì đó như thế này:

ViewController

#import "ViewController.h" 
#import "AnimatedView.h" 
#include <stdlib.h> 

@interface ViewController() 

@property (nonatomic, strong) CADisplayLink *displayLink; 
@property (weak, nonatomic) IBOutlet AnimatedView *viewToAnimate; 

@end 

@implementation ViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateFrame)]; 
    [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 
} 

- (void)updateFrame { 
    [self.viewToAnimate updateAnimation]; 
} 

- (IBAction)updateAnimationTapped:(id)sender { 
    self.viewToAnimate.value = arc4random_uniform(101)/100.0; 
    NSLog(@"Next animation value: %f", self.viewToAnimate.value); 
} 

@end 

AnimatedView

#import "AnimatedView.h" 
#import "RSTimingFunction.h" 

@interface AnimatedView() 
{ 
    CGFloat _lastValue; 
    CGFloat _progressStep; 
    CGFloat _currentProgress; 
} 

@property (nonatomic, strong) RSTimingFunction *animationProgress; 

@end 

@implementation AnimatedView 

- (instancetype)initWithCoder:(NSCoder *)aDecoder 
{ 
    if ((self = [super initWithCoder:aDecoder])) 
    { 
     _progressStep = 0.01; // defines animation speed 
     _currentProgress = 1.0; 
     self.animationProgress = [RSTimingFunction timingFunctionWithName:kRSTimingFunctionEaseInEaseOut]; 
    } 

    return self; 
} 

- (void)setValue:(CGFloat)value { 
    if (_value != value) 
    { 
     _lastValue = _value; 
     _value = value; 
     _currentProgress = 0.0; 
    } 
} 

- (void)updateAnimation 
{ 
    if (_currentProgress > 1.0) 
     return; 

    _currentProgress += _progressStep; 
    CGFloat currentAnimationValue = _lastValue + (_value - _lastValue) * [self.animationProgress valueForX:_currentProgress]; 

    self.alpha = currentAnimationValue; // as an example animate alpha 
} 

@end 

Như đã nói, bạn thậm chí có thể thiết lập 2 điểm kiểm soát để tạo ra một hàm thời gian được mô hình hóa trên một đường cong Bezier khối.

self.animationProgress = [RSTimingFunction timingFunctionWithControlPoint1:CGPointMake(0.6, 0.6) controlPoint2:CGPointMake(0.1, 0.8)]; 

Mà sẽ tạo ra hình ảnh động sau thời gian (được sản xuất sử dụng CAMediaTimingFunction playground)

enter image description here

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