1.1 曲线和弹性动画的定义与开发

一、曲线动画的贝塞尔插值法

iOS开发(利用 Core Animation )

```CABasicAnimation *animation = [CABasicAnimation animation];
animation.keyPath = @"position.x";
animation.fromValue = @77;
animation.toValue = @455;
animation.duration = 1;
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
animation.timingFunction =[CAMediaTimingFunction  functionWithControlPoints:0.78:0.36:0.14:1.09];

Android开发：

`PathInterpolator`

```div {
-webkit-transition: all 600ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
transition:         all 600ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
}```

二、函数动画

1. 设计者使用 AE 制作弹性动画时，使用表达式
``````if (nearestKeyIndex > 0 && currentTime < 1) {
calculatedVelocity = velocityAtTime(key(nearestKeyIndex).time - thisComp.frameDuration / 10);
amplitude = 1.1;
frequency = 2.0;
decay = 4.0;
value + calculatedVelocity * amplitude * Math.sin(frequency * currentTime * 2 * Math.PI) / Math.exp(decay * currentTime);
} else {
value;
}
``````

1. 同样的，在 AE 中也可以利用函数描述近似贝塞尔曲线的缓动动画（Ease&Wizz JS 文件下载
``````//去
var p = 0.8;		// period for elastic
var a = 50;			// amplitude for elastic
var s = 1.70158;	// overshoot amount for "back"
function outQuart(t, b, c, d, a, p) {
return -c * ((t=t/d-1)*t*t*t - 1) + b;
}
//回
var p = 0.8;		// period for elastic
var a = 50;			// amplitude for elastic
var s = 1.70158;	// overshoot amount for "back"
function inOutQuad(t, b, c, d, a, p) {
if ((t/=d/2) < 1) return c/2*t*t + b;
return -c/2 * ((--t)*(t-2) - 1) + b;
}
``````

3.1 案例1:利用函数可以将手势交互变化量动画属性良好结合，实现真实、细腻的交互效果（案例来自 Kitten Yang 的 《A Guide to iOS animation》 Github地址

``````-(void)panGestureRecognized:(UIPanGestureRecognizer *)pan{

static CGPoint initialPoint;
CGFloat factorOfAngle = 0.0f;
CGFloat factorOfScale = 0.0f;
CGPoint transition = [pan translationInView:self.superview];

if (pan.state == UIGestureRecognizerStateBegan) {

initialPoint = self.center;

}else if(pan.state == UIGestureRecognizerStateChanged){

self.center = CGPointMake(initialPoint.x,initialPoint.y + transition.y);

CGFloat Y =MIN(SCROLLDISTANCE,MAX(0,ABS(transition.y)));

//一个开口向下,顶点(SCROLLDISTANCE/2,1),过(0,0),(SCROLLDISTANCE,0)的二次函数
factorOfAngle = MAX(0,-4/(SCROLLDISTANCE*SCROLLDISTANCE)*Y*(Y-SCROLLDISTANCE));
//一个开口向下,顶点(SCROLLDISTANCE,1),过(0,0),(2*SCROLLDISTANCE,0)的二次函数
factorOfScale = MAX(0,-1/(SCROLLDISTANCE*SCROLLDISTANCE)*Y*(Y-2*SCROLLDISTANCE));

CATransform3D t = CATransform3DIdentity;
t.m34  = 1.0/-1000;
t = CATransform3DRotate(t,factorOfAngle*(M_PI/5), transition.y>0?-1:1, 0, 0);
t = CATransform3DScale(t, 1-factorOfScale*0.2, 1-factorOfScale*0.2, 0);

self.layer.transform = t;
}
}
``````

3.2 案例2:获取 Pan 手势的手指位置后，传递给贝塞尔图形，实现拉窗帘一般的效果。

``````func createPulledPath(width:CGFloat,point:CGPoint) -> UIBezierPath{
let height = view.bounds.height
let offset = width + point.x

let path = UIBezierPath()
path.moveToPoint(CGPoint(x: -mtExtenedEdgesOffset, y: -mtExtenedEdgesOffset))

controlPoint1: CGPoint(x: width, y: point.y * mtControlPointRatio),
controlPoint2: CGPoint(x: offset, y: point.y - mtControlPointPulledDistance))

path.addCurveToPoint(CGPoint(x: width, y: height + mtExtenedEdgesOffset),
controlPoint1: CGPoint(x: offset, y: point.y + mtControlPointPulledDistance),
controlPoint2: CGPoint(x: width, y: point.y + (height - point.y) * (1 - mtControlPointRatio)))

path.addLineToPoint(CGPoint(x: -mtExtenedEdgesOffset, y: height + mtExtenedEdgesOffset))

path.closePath()
return path

}
``````

``````func usefourmulaGetX(width:CGFloat,point:CGPoint,x0:CGFloat,x1:CGFloat,x2:CGFloat,x3:CGFloat,t:CGFloat) -> CGFloat {
let xValue:CGFloat = x0*(1-t)*(1-t)*(1-t) + 3*x1*t*(1-t)*(1-t) + 3*x2*t*t*(1-t) + x3*t*t*t
return xValue
}

func usefourmulaGetY(width:CGFloat,point:CGPoint,y0:CGFloat,y1:CGFloat,y2:CGFloat,y3:CGFloat,t:CGFloat) -> CGFloat {
let yValue:CGFloat = y0*(1-t)*(1-t)*(1-t) + 3*y1*t*(1-t)*(1-t) + 3*y2*t*t*(1-t) + y3*t*t*t
return yValue
}
``````

4.安卓开发时，使用 RapidInterpolator ，也可以调节原声插值器动画 以及 easing.net那套Easing函数动画

1.缓动函数速查表

4.AHEasing 开源库 (可以尝试简单修改以便与 Ease & Wizz 的JS函数对接)

三、弹性动画

1.使用 UIkit Dynamic 中的SnapBehavior

2.使用 UIView 动画的 Spring 形式

3.使用上文提到的函数来描述一根弹性动画曲线

``````//UI动力学
self.Cardview.center = CGPointMake(160, 219.5)
self.snapBehavior = UISnapBehavior(item: self.Cardview, snapToPoint: CGPointMake(160, 219.5))

//UIView - Spring
UIView.animateWithDuration(0.5, delay: 0,usingSpringWithDamping: 0.7, initialSpringVelocity: 0, options: .CurveEaseOut, animations: {
self.introbtn.frame.origin.y = 692
}, completion: { finished in
})
``````

POP动画的写法类似CAAnimation：

``````    POPSpringAnimation *switchFrameAnim = [POPSpringAnimation animation];
switchFrameAnim.property = [POPAnimatableProperty propertyWithName:kPOPViewFrame];
switchFrameAnim.springBounciness = 20;
switchFrameAnim.springSpeed = 10;
switchFrameAnim.toValue = [NSValue valueWithCGRect:CGRectMake(137.5, 450,  100, 100)];
``````

POP动画可以做 CompletionBlock：

``````    anim.completionBlock = ^(POPAnimation *anim, BOOL finished) {
if(finished){NSLog(@"Animation finished!");}};
}
``````

POP动画可以获取动画的 Progress：

``````//获取某一动画属性的Progress
POPSpringAnimation *progressAnim = [POPSpringAnimation animation];
progressAnim.springBounciness = smallBounciness;
progressAnim.springSpeed = smallSpeed;
progressAnim.property = [POPAnimatableProperty propertyWithName:@"popAnimationProgress" initializer:^(POPMutableAnimatableProperty *prop) {
prop.readBlock = ^(ViewController *obj, CGFloat values[]) {
values[0] = obj.popAnimationProgress;
};
prop.writeBlock = ^(ViewController *obj, const CGFloat values[]) {
obj.popAnimationProgress = values[0];
};
prop.threshold = 0.001;
}];
``````

``````//阴影动画
//Custom Animation Property
};
// write value
prop.writeBlock = ^(CALayer * shadowOpacity, const CGFloat values[]) {
};
// dynamics threshold
prop.threshold = 0.01;
}];
``````

5.转换 spring-rk4 到 Facebook pop bouncy animation Framer JS 的 spring-rk4动画，可以使用ReboundJS中的转化公式，转为POP动画，方便了 iOS 开发 和 Web 开发

```convert = (tension, friction) ->
result =
tension :  Utils.round (tension - 194.0) / 3.62 + 30.0
friction : Utils.round (friction - 25.0) / 3.0 + 8.0
return result

print convert 600, 60
# » {tension:142, friction:20}```

1.POP使用指南

2.POP进阶指南

四、定义常用曲线动画

bezier(0.33,0,0.25,1) EaseOut1
bezier(0.33,0,0.33,1) EaseOut2
bezier(0.33,0,0.46,1) EaseOut3
bezier(0.55,0,0.1,1) EaseOut4(SwiftOut)
bezier(0.78,0.36,0.14,1.09) EaseOut5(Back)
bezier(0.66,0,0.33,1) EaseInOut1
bezier(0.33,0,0.66,1) EaseInOut2

Clone this wiki locally
You can’t perform that action at this time.