Created
June 22, 2015 21:32
-
-
Save felixvisee/6afbb6e21331ec128732 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
IFTTTFrameAnimation *wordmarkFrameAnimation = [IFTTTFrameAnimation animationWithView:self.wordmark]; | |
[wordmarkFrameAnimation addKeyframeForTime:0 value:[[MyCustomValue alloc] initWithCGRect:CGRectMake(0, 0, 189, 50) controlPoint1:CGPointMake(320, 80) controlPoint2:CGPointMake(0, 240)]]; | |
[wordmarkFrameAnimation addKeyframeForTime:1 value:[[MyCustomValue alloc] initWithCGRect:CGRectMake(320, 320, 189, 50) controlPoint1:CGPointZero controlPoint2:CGPointZero]]; | |
[self.animator addAnimation:wordmarkFrameAnimation]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Foundation/Foundation.h> | |
#import <JazzHands/IFTTTJazzHands.h> | |
@interface MyCustomValue : NSValue <IFTTTInterpolatable> | |
@property (nonatomic, assign, readonly) CGPoint controlPoint1; | |
@property (nonatomic, assign, readonly) CGPoint controlPoint2; | |
- (instancetype)initWithCGRect:(CGRect)rect controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2; | |
- (CGRect)interpolateCGRectFrom:(CGRect)fromValue to:(CGRect)toValue withProgress:(CGFloat)progress; | |
- (CGPoint)interpolateCGPointFrom:(CGPoint)fromValue to:(CGPoint)toValue withProgress:(CGFloat)progress; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "MyCustomValue.h" | |
#if CGFLOAT_IS_DOUBLE | |
#define POW(X, Y) pow(X, Y) | |
#else | |
#define POW(X, Y) powf(X, Y) | |
#endif | |
@interface MyCustomValue () | |
@property (nonatomic, copy, readonly) NSValue *underlyingValue; | |
@end | |
@implementation MyCustomValue | |
- (instancetype)initWithCGRect:(CGRect)rect controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2 | |
{ | |
self = [self init]; | |
if (self == nil) { | |
return nil; | |
} | |
_underlyingValue = [NSValue valueWithCGRect:rect]; | |
_controlPoint1 = controlPoint1; | |
_controlPoint2 = controlPoint2; | |
return self; | |
} | |
- (NSValue *)interpolateTo:(NSValue *)toValue withProgress:(CGFloat)progress | |
{ | |
CGRect rect = [self interpolateCGRectFrom:[self CGRectValue] to:[toValue CGRectValue] withProgress:progress]; | |
return [NSValue valueWithCGRect:rect]; | |
} | |
- (CGRect)interpolateCGRectFrom:(CGRect)fromValue to:(CGRect)toValue withProgress:(CGFloat)progress | |
{ | |
CGPoint origin = [self interpolateCGPointFrom:fromValue.origin to:toValue.origin withProgress:progress]; | |
CGSize size = [self.class interpolateCGSizeFrom:fromValue.size to:toValue.size withProgress:progress]; | |
return (CGRect){ | |
.origin = { .x = origin.x, .y = origin.y }, | |
.size = { .width = size.width, .height = size.height } | |
}; | |
} | |
- (CGPoint)interpolateCGPointFrom:(CGPoint)fromValue to:(CGPoint)toValue withProgress:(CGFloat)progress | |
{ | |
// B(t) = (1 - t) ^ 3 * s + 3 * (1 - t) ^ 2 * t * cp1 + 3 * (1 - t) * t ^ 2 * cp2 + t ^ 3 * e | |
CGFloat x = POW(1 - progress, 3) * fromValue.x | |
+ 3 * POW(1 - progress, 2) * progress * self.controlPoint1.x | |
+ 3 * (1 - progress) * POW(progress, 2) * self.controlPoint2.x | |
+ POW(progress, 3) * toValue.x; | |
CGFloat y = POW(1 - progress, 3) * fromValue.y | |
+ 3 * POW(1 - progress, 2) * progress * self.controlPoint1.y | |
+ 3 * (1 - progress) * POW(progress, 2) * self.controlPoint2.y | |
+ POW(progress, 3) * toValue.y; | |
return (CGPoint){ .x = x, .y = y }; | |
} | |
- (void)getValue:(void *)value | |
{ | |
[self.underlyingValue getValue:value]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment