You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
117 lines
4.2 KiB
117 lines
4.2 KiB
/** |
|
Copyright (c) 2014-present, Facebook, Inc. |
|
All rights reserved. |
|
|
|
This source code is licensed under the BSD-style license found in the |
|
LICENSE file in the root directory of this source tree. An additional grant |
|
of patent rights can be found in the PATENTS file in the same directory. |
|
*/ |
|
|
|
#import "POPAnimationExtras.h" |
|
#import "POPAnimationPrivate.h" |
|
|
|
#if TARGET_OS_IPHONE |
|
#import <UIKit/UIKit.h> |
|
#endif |
|
|
|
#if TARGET_IPHONE_SIMULATOR |
|
UIKIT_EXTERN float UIAnimationDragCoefficient(); // UIKit private drag coefficient, use judiciously |
|
#endif |
|
|
|
#import "POPMath.h" |
|
|
|
CGFloat POPAnimationDragCoefficient() |
|
{ |
|
#if TARGET_IPHONE_SIMULATOR |
|
return UIAnimationDragCoefficient(); |
|
#else |
|
return 1.0; |
|
#endif |
|
} |
|
|
|
@implementation CAAnimation (POPAnimationExtras) |
|
|
|
- (void)pop_applyDragCoefficient |
|
{ |
|
CGFloat k = POPAnimationDragCoefficient(); |
|
if (k != 0 && k != 1) |
|
self.speed = 1 / k; |
|
} |
|
|
|
@end |
|
|
|
@implementation POPSpringAnimation (POPAnimationExtras) |
|
|
|
static const CGFloat POPBouncy3NormalizationRange = 20.0; |
|
static const CGFloat POPBouncy3NormalizationScale = 1.7; |
|
static const CGFloat POPBouncy3BouncinessNormalizedMin = 0.0; |
|
static const CGFloat POPBouncy3BouncinessNormalizedMax = 0.8; |
|
static const CGFloat POPBouncy3SpeedNormalizedMin = 0.5; |
|
static const CGFloat POPBouncy3SpeedNormalizedMax = 200; |
|
static const CGFloat POPBouncy3FrictionInterpolationMax = 0.01; |
|
|
|
+ (void)convertBounciness:(CGFloat)bounciness speed:(CGFloat)speed toTension:(CGFloat *)outTension friction:(CGFloat *)outFriction mass:(CGFloat *)outMass |
|
{ |
|
double b = POPNormalize(bounciness / POPBouncy3NormalizationScale, 0, POPBouncy3NormalizationRange); |
|
b = POPProjectNormal(b, POPBouncy3BouncinessNormalizedMin, POPBouncy3BouncinessNormalizedMax); |
|
|
|
double s = POPNormalize(speed / POPBouncy3NormalizationScale, 0, POPBouncy3NormalizationRange); |
|
|
|
CGFloat tension = POPProjectNormal(s, POPBouncy3SpeedNormalizedMin, POPBouncy3SpeedNormalizedMax); |
|
CGFloat friction = POPQuadraticOutInterpolation(b, POPBouncy3NoBounce(tension), POPBouncy3FrictionInterpolationMax); |
|
|
|
tension = POP_ANIMATION_TENSION_FOR_QC_TENSION(tension); |
|
friction = POP_ANIMATION_FRICTION_FOR_QC_FRICTION(friction); |
|
|
|
if (outTension) { |
|
*outTension = tension; |
|
} |
|
|
|
if (outFriction) { |
|
*outFriction = friction; |
|
} |
|
|
|
if (outMass) { |
|
*outMass = 1.0; |
|
} |
|
} |
|
|
|
+ (void)convertTension:(CGFloat)tension friction:(CGFloat)friction toBounciness:(CGFloat *)outBounciness speed:(CGFloat *)outSpeed |
|
{ |
|
// Convert to QC values, in which our calculations are done. |
|
CGFloat qcFriction = QC_FRICTION_FOR_POP_ANIMATION_FRICTION(friction); |
|
CGFloat qcTension = QC_TENSION_FOR_POP_ANIMATION_TENSION(tension); |
|
|
|
// Friction is a function of bounciness and tension, according to the following: |
|
// friction = POPQuadraticOutInterpolation(b, POPBouncy3NoBounce(tension), POPBouncy3FrictionInterpolationMax); |
|
// Solve for bounciness, given a tension and friction. |
|
|
|
CGFloat nobounceTension = POPBouncy3NoBounce(qcTension); |
|
CGFloat bounciness1, bounciness2; |
|
|
|
POPQuadraticSolve((nobounceTension - POPBouncy3FrictionInterpolationMax), // a |
|
2 * (POPBouncy3FrictionInterpolationMax - nobounceTension), // b |
|
(nobounceTension - qcFriction), // c |
|
bounciness1, // x1 |
|
bounciness2); // x2 |
|
|
|
|
|
// Choose the quadratic solution within the normalized bounciness range |
|
CGFloat projectedNormalizedBounciness = (bounciness2 < POPBouncy3BouncinessNormalizedMax) ? bounciness2 : bounciness1; |
|
CGFloat projectedNormalizedSpeed = qcTension; |
|
|
|
// Reverse projection + normalization |
|
CGFloat bounciness = ((POPBouncy3NormalizationRange * POPBouncy3NormalizationScale) / (POPBouncy3BouncinessNormalizedMax - POPBouncy3BouncinessNormalizedMin)) * (projectedNormalizedBounciness - POPBouncy3BouncinessNormalizedMin); |
|
CGFloat speed = ((POPBouncy3NormalizationRange * POPBouncy3NormalizationScale) / (POPBouncy3SpeedNormalizedMax - POPBouncy3SpeedNormalizedMin)) * (projectedNormalizedSpeed - POPBouncy3SpeedNormalizedMin); |
|
|
|
// Write back results |
|
if (outBounciness) { |
|
*outBounciness = bounciness; |
|
} |
|
|
|
if (outSpeed) { |
|
*outSpeed = speed; |
|
} |
|
} |
|
|
|
@end
|
|
|