Skip to content

Commit

Permalink
Added all of Robert Penner's easing equations, moved operations to th…
Browse files Browse the repository at this point in the history
…eir own class
  • Loading branch information
Dominik Hofmann committed Jul 9, 2011
1 parent 826859b commit 435fc91
Show file tree
Hide file tree
Showing 12 changed files with 441 additions and 106 deletions.
8 changes: 8 additions & 0 deletions LICENSE
@@ -0,0 +1,8 @@
Copyright (c) 2011, Dominik Hofmann
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Empty file removed README
Empty file.
114 changes: 114 additions & 0 deletions README.md
@@ -0,0 +1,114 @@
PRTween
===

PRTween is a lightweight tweening library built for iOS. While Apple has done an incredible job with UIView Animations and Core Animation, there are some conscious limitations in these systems that are difficult to get around. PRTween is a great alternative if you'd like to:

* Animate a property Apple won't allow you to
* Ensure that <pre>[someView layoutSubviews]</pre> is respected during an animation
* Tween arbitrary numerical values, such as: sound volume, scroll position, a price counter, or many others
* Define your timing curve as a function rather than a bezier with control points

Installation
===

Simply grab the PRTween and PRTweenTimingFunction files from /lib/ and get them into your project.

Example Project
===

If you prefer to learn by looking at code that is already written, you can check out the example project in /example/

Usage
===

At its core, PRTween is broken into two components.

A **period** is a representation of three points in time (beginning, current, and end) for a particular value that you plan on tweening. For example, suppose that are tweening a value from 100 to 200 over the course of 3 seconds. You can create an object to represent that period like this:

PRTweenPeriod *period = [PRTweenPeriod periodWithStartValue:100 endValue:200 duration:3];

The second component that makes up PRTween is an **operation**. An operation contains logistic information about how a period should play out, as well as what should happen while it does. You can think of a period as an abstract representation of work that should be carried out, and an operation as the worker who decides *how* it gets carried out. An operation might get added to the queue like this:

PRTweenOperation *operation = [[PRTweenOperation new] autorelease];
operation.period = period;
operation.target = self;
operation.timingFunction = &PRTweenTimingFunctionLinear;
operation.updateSelector = @selector(update:)

The code creates a new operation that carries out a tween over the period we defined earlier. Additionally, you've told the operation to call the <pre>update:</pre> selector every time the value is adjusted. <pre>update:</pre> might look like this:

- (void)update:(PRTweenPeriod*)period {
NSLog(@"%f", period.tweenedValue);
}

Finally, you will need to add the operation to the queue.

[[PRTween sharedInstance] addTweenOperation:operation]

As soon as you've done this and run your code, you should be able to see a console trace of a value moving from 100 to 200 over the course of 3 seconds. If you wanted to apply this to an object on screen, it could be as simple as changing <pre>update:</pre> to the following:

// will animate the Y offset of testView from 100 to 200 over the course of 3 seconds
- (void)update:(PRTweenPeriod*)period {
testView.frame = CGRectMake(0, period.tweenedValue, 100, 100);
}

Timing Functions
===

Timing functions are a key feature of PRTween, and allow you to modify how an operation interprets a period. For example, try changing <pre>operation.period</pre> from <pre>&PRTweenTimingFunctionLinear</pre> to <pre>&PRTweenTimingFunctionBounceOut</pre> and running your code again. You should see a similar animation play out, but this time a bounce will be added to the end of it. PRTween comes bundled with a number of timing functions for your convenience:

* PRTweenTimingFunctionLinear
* PRTweenTimingFunctionBack*[In / Out / InOut]*
* PRTweenTimingFunctionBounce*[In / Out / InOut]*
* PRTweenTimingFunctionCircOut*[In / Out / InOut]*
* PRTweenTimingFunctionCubicOut*[In / Out / InOut]*
* PRTweenTimingFunctionElasticOut*[In / Out / InOut]*
* PRTweenTimingFunctionExpoOut*[In / Out / InOut]*
* PRTweenTimingFunctionQuadOut*[In / Out / InOut]*
* PRTweenTimingFunctionQuartOut*[In / Out / InOut]*
* PRTweenTimingFunctionQuintOut*[In / Out / InOut]*
* PRTweenTimingFunctionSineOut*[In / Out / InOut]*

We encourage you to experiment with PRTween's timing functions in your applications to see which ones you like best.

Custom Functions
---

One of the most powerful capabilities of PRTween is the ability to write your own timing functions. In lieu of documentation at this time, have a look through PRTweenTimingFunctions.m for example timing functions.

Advanced
===

API docs are coming with the next push. Until then, you are encouraged to dig through the code for details on advanced functionality. PRTween is incredibly minimal, so you can probably figure everything out in an hour or two.

Contributing
===

PRTween is incredibly young, so there many rules right now.

* Fork it
* Fix it or add it
* Add yourself to the contributor list
* Commit
* Send a pull request

Contributors
---

* [This link](https://github.com/dominikhofmann/)Dominik Hofmann

License
===
Surprise! It's a BSD license.

<pre>
Copyright (c) 2011, Dominik Hofmann
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</pre>

20 changes: 16 additions & 4 deletions example/PRTween.xcodeproj/project.pbxproj
Expand Up @@ -16,7 +16,8 @@
B25002D2139558F700670D11 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = B25002D0139558F700670D11 /* MainWindow.xib */; };
B25002D5139558F700670D11 /* PRTweenExampleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B25002D4139558F700670D11 /* PRTweenExampleViewController.m */; };
B25002D8139558F700670D11 /* PRTweenExampleViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = B25002D6139558F700670D11 /* PRTweenExampleViewController.xib */; };
B25002E01395591F00670D11 /* PRTween.m in Sources */ = {isa = PBXBuildFile; fileRef = B25002DF1395591F00670D11 /* PRTween.m */; };
B4A2EBFD13C8AFAE006EB549 /* PRTweenTimingFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = B4A2EBFB13C8AFAE006EB549 /* PRTweenTimingFunctions.m */; };
B4F3069513C8BFCA00355204 /* PRTween.m in Sources */ = {isa = PBXBuildFile; fileRef = B4F3069313C8BFCA00355204 /* PRTween.m */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand All @@ -35,7 +36,9 @@
B25002D4139558F700670D11 /* PRTweenExampleViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PRTweenExampleViewController.m; sourceTree = "<group>"; };
B25002D7139558F700670D11 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/PRTweenExampleViewController.xib; sourceTree = "<group>"; };
B25002DE1395591F00670D11 /* PRTween.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PRTween.h; path = ../lib/PRTween.h; sourceTree = "<group>"; };
B25002DF1395591F00670D11 /* PRTween.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PRTween.m; path = ../lib/PRTween.m; sourceTree = "<group>"; };
B4A2EBFB13C8AFAE006EB549 /* PRTweenTimingFunctions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PRTweenTimingFunctions.m; path = ../lib/PRTweenTimingFunctions.m; sourceTree = "<group>"; };
B4A2EBFC13C8AFAE006EB549 /* PRTweenTimingFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PRTweenTimingFunctions.h; path = ../lib/PRTweenTimingFunctions.h; sourceTree = "<group>"; };
B4F3069313C8BFCA00355204 /* PRTween.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PRTween.m; path = ../lib/PRTween.m; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -84,7 +87,9 @@
isa = PBXGroup;
children = (
B25002DE1395591F00670D11 /* PRTween.h */,
B25002DF1395591F00670D11 /* PRTween.m */,
B4F3069313C8BFCA00355204 /* PRTween.m */,
B4A2EBFB13C8AFAE006EB549 /* PRTweenTimingFunctions.m */,
B4A2EBFC13C8AFAE006EB549 /* PRTweenTimingFunctions.h */,
);
name = PRTween;
sourceTree = "<group>";
Expand Down Expand Up @@ -180,7 +185,8 @@
B25002CC139558F700670D11 /* main.m in Sources */,
B25002CF139558F700670D11 /* PRTweenExampleAppDelegate.m in Sources */,
B25002D5139558F700670D11 /* PRTweenExampleViewController.m in Sources */,
B25002E01395591F00670D11 /* PRTween.m in Sources */,
B4A2EBFD13C8AFAE006EB549 /* PRTweenTimingFunctions.m in Sources */,
B4F3069513C8BFCA00355204 /* PRTween.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -256,8 +262,11 @@
GCC_DYNAMIC_NO_PIC = NO;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "PRTween-Prefix.pch";
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
INFOPLIST_FILE = "PRTween-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 3.0;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
WRAPPER_EXTENSION = app;
};
name = Debug;
Expand All @@ -269,8 +278,11 @@
COPY_PHASE_STRIP = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "PRTween-Prefix.pch";
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
INFOPLIST_FILE = "PRTween-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 3.0;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
WRAPPER_EXTENSION = app;
};
Expand Down
7 changes: 0 additions & 7 deletions example/PRTweenExampleAppDelegate.h
@@ -1,10 +1,3 @@
//
// JSTweenAppDelegate.h
// JSTween
//
// Created by Dominik Hofmann on 5/31/11.
// Copyright 2011 Jetsetter. All rights reserved.
//

#import <UIKit/UIKit.h>

Expand Down
8 changes: 0 additions & 8 deletions example/PRTweenExampleAppDelegate.m
@@ -1,13 +1,5 @@
//
// JSTweenAppDelegate.m
// JSTween
//
// Created by Dominik Hofmann on 5/31/11.
// Copyright 2011 Jetsetter. All rights reserved.
//

#import "PRTweenExampleAppDelegate.h"

#import "PRTweenExampleViewController.h"

@implementation PRTweenExampleAppDelegate
Expand Down
10 changes: 2 additions & 8 deletions example/PRTweenExampleViewController.h
@@ -1,17 +1,11 @@
//
// JSTweenViewController.h
// JSTween
//
// Created by Dominik Hofmann on 5/31/11.
// Copyright 2011 Jetsetter. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "PRTween.h"

@interface PRTweenExampleViewController : UIViewController {

UIView *testView;
NSDictionary *activeTweenOperation;
PRTweenOperation *activeTweenOperation;

}

Expand Down
1 change: 0 additions & 1 deletion example/PRTweenExampleViewController.m
@@ -1,6 +1,5 @@

#import "PRTweenExampleViewController.h"
#import "PRTween.h"

@implementation PRTweenExampleViewController

Expand Down
32 changes: 21 additions & 11 deletions lib/PRTween.h
@@ -1,13 +1,6 @@

#import <Foundation/Foundation.h>

CGFloat PRTweenTimingFunctionLinear (CGFloat, CGFloat, CGFloat, CGFloat);
CGFloat PRTweenTimingFunctionBounceOut (CGFloat, CGFloat, CGFloat, CGFloat);
CGFloat PRTweenTimingFunctionBounceIn (CGFloat, CGFloat, CGFloat, CGFloat);
CGFloat PRTweenTimingFunctionBounceInOut (CGFloat, CGFloat, CGFloat, CGFloat);
CGFloat PRTweenTimingFunctionQuintOut (CGFloat, CGFloat, CGFloat, CGFloat);
CGFloat PRTweenTimingFunctionQuintIn (CGFloat, CGFloat, CGFloat, CGFloat);
CGFloat PRTweenTimingFunctionQuintInOut (CGFloat, CGFloat, CGFloat, CGFloat);
#import "PRTweenTimingFunctions.h"

@interface PRTweenPeriod : NSObject {
CGFloat startValue;
Expand All @@ -29,6 +22,22 @@ CGFloat PRTweenTimingFunctionQuintInOut (CGFloat, CGFloat, CGFloat, CGFloat);

@end

@interface PRTweenOperation : NSObject {
PRTweenPeriod *period;
NSObject *target;
SEL updateSelector;
SEL completeSelector;
CGFloat (*timingFunction)(CGFloat, CGFloat, CGFloat, CGFloat);
}

@property (nonatomic, retain) PRTweenPeriod *period;
@property (nonatomic, retain) NSObject *target;
@property (nonatomic) SEL updateSelector;
@property (nonatomic) SEL completeSelector;
@property (nonatomic, assign) CGFloat (*timingFunction)(CGFloat, CGFloat, CGFloat, CGFloat);

@end

@interface PRTween : NSObject {
NSMutableArray *tweenOperations;
NSMutableArray *expiredTweenOperations;
Expand All @@ -39,8 +48,9 @@ CGFloat PRTweenTimingFunctionQuintInOut (CGFloat, CGFloat, CGFloat, CGFloat);
@property (nonatomic, readonly) CGFloat timeOffset;

+ (PRTween *)sharedInstance;
- (NSDictionary*)addTweenPeriod:(PRTweenPeriod *)period target:(NSObject *)target selector:(SEL)selector;
- (NSDictionary*)addTweenPeriod:(PRTweenPeriod *)period target:(NSObject *)target selector:(SEL)selector timingFunction:(CGFloat (*)(CGFloat, CGFloat, CGFloat, CGFloat))timingFunction;
- (void)removeTweenOperation:(NSDictionary*)tweenOperation;
- (PRTweenOperation*)addOperation:(PRTweenOperation*)operation;
- (PRTweenOperation*)addTweenPeriod:(PRTweenPeriod *)period target:(NSObject *)target selector:(SEL)selector;
- (PRTweenOperation*)addTweenPeriod:(PRTweenPeriod *)period target:(NSObject *)target selector:(SEL)selector timingFunction:(CGFloat (*)(CGFloat, CGFloat, CGFloat, CGFloat))timingFunction;
- (void)removeTweenOperation:(PRTweenOperation*)tweenOperation;

@end

0 comments on commit 435fc91

Please sign in to comment.