| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- /**
- 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 coeffient, 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
|