理想效果
实际效果
思考
1.位置上的变化(spring动画)
UIView
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);
<p>
CASpringAnimation
NS_AVAILABLE_IOS(9_0);
<p>
facebook/pop
UIView | CASpringAnimation | facebook/Pop |
---|---|---|
方便用,效果一般,但是不灵活,功能不强 | iOS9 | 功能强大,效果好,但是复杂 |
<p>
<p>
2.形态上的变化(变小,圆边的弧度挤压)
CGAffineTransform/CATransform3D
CGAffineTransformMakeScale(CGFloat sx,CGFloat sy)
<p>
<p>
<p>
<p>
学习
KYAnimatedPageControl(@github)
实现原理
三阶贝塞尔曲线拟合1/4圆
带入三个点计算。
h = 0.552;
CGFloat extra = (self.currentRect.size.width * 2 / 5) * factor;//factor 0~1 随时间变化
CGFloat offset = self.currentRect.size.width / 3.6; //设置2/0.552 = 3.6 出来的弧度拟合1/4圆形
CGPoint pointA = CGPointMake(rectCenter.x ,self.currentRect.origin.y + extra);
CGPoint pointB = CGPointMake( rectCenter.x + self.currentRect.size.width/2,rectCenter.y);
CGPoint pointC = CGPointMake(rectCenter.x ,rectCenter.y + self.currentRect.size.height/2 - extra);
CGPoint pointD = CGPointMake(self.currentRect.origin.x, rectCenter.y);//..有省略..
CGPoint c1 = CGPointMake(pointA.x + offset, pointA.y);
CGPoint c2 = CGPointMake(pointB.x, pointB.y - offset);
CGPoint c3 = CGPointMake(pointB.x, pointB.y + offset);
CGPoint c4 = CGPointMake(pointC.x + offset, pointC.y);
CGPoint c5 = CGPointMake(pointC.x - offset, pointC.y);
CGPoint c6 = CGPointMake(pointD.x, pointD.y + offset);
CGPoint c7 = CGPointMake(pointD.x, pointD.y - offset);
CGPoint c8 = CGPointMake(pointA.x - offset, pointA.y);
UIBezierPath* ovalPath = [UIBezierPath bezierPath];
[ovalPath moveToPoint: pointA];
[ovalPath addCurveToPoint:pointB controlPoint1:c1 controlPoint2:c2];
[ovalPath addCurveToPoint:pointC controlPoint1:c3 controlPoint2:c4];
[ovalPath addCurveToPoint:pointD controlPoint1:c5 controlPoint2:c6];
[ovalPath addCurveToPoint:pointA controlPoint1:c7 controlPoint2:c8];
[ovalPath closePath];
CGContextAddPath(ctx, ovalPath.CGPath);
CGContextSetFillColorWithColor(ctx, self.indicatorColor.CGColor);
CGContextFillPath(ctx);
关键帧动画 (对应参数factor)
CAKeyframeAnimation
阻尼振动
-(NSMutableArray *) springAnimationValues:(id)fromValue toValue:(id)toValue usingSpringWithDamping:(CGFloat)damping initialSpringVelocity:(CGFloat)velocity duration:(CGFloat)duration{
//60个关键帧
NSInteger numOfFrames = duration * 60;
NSMutableArray *values = [NSMutableArray arrayWithCapacity:numOfFrames];
for (NSInteger i = 0; i < numOfFrames; i++) {
[values addObject:@(0.0)];
}
CGFloat diff = [toValue floatValue] - [fromValue floatValue];
for (NSInteger frame = 0; frame<numOfFrames; frame++) {
CGFloat x = (CGFloat)frame / (CGFloat)numOfFrames;
CGFloat value = [toValue floatValue] - diff * (pow(M_E, -damping * x) * cos(velocity * x)); // y = 1-e^{-5x} * cos(30x)
values[frame] = @(value);
}
return values;
}
<p>
<p>
<p>
<p>
自己的修改
1.根据移动方向挤压小球
_angle = atanf((desPoint.y - self.position.y)/(desPoint.x - self.position.x));
CGFloat extra = (self.currentRect.size.width * 2 / 5) * _factor;
CGFloat radius = _currentRect.size.width/2 - extra;
CGFloat offset = self.currentRect.size.width / 3.6; //设置3.6 出来的弧度最像圆形
square.pointB = [SCCircleMath caculatePointFromAngle:_angle CirCleCenter:self.position cirCleRadius:radius1];
square.pointC = [SCCircleMath caculatePointFromAngle:_angle + M_PI_4*2 CirCleCenter:self.position cirCleRadius:radius2];
square.pointD = [SCCircleMath caculatePointFromAngle:_angle + M_PI_4*4 CirCleCenter:self.position cirCleRadius:radius1];
square.pointA = [SCCircleMath caculatePointFromAngle:_angle + M_PI_4*6 CirCleCenter:self.position cirCleRadius:radius1];
CGFloat sinValue = offset * sinf(_angle);
CGFloat cosValue = offset * cosf(_angle);
CGPoint c1 = CGPointMake(square.pointA.x + sinValue, square.pointA.y - cosValue);
CGPoint c2 = CGPointMake(square.pointB.x - cosValue, square.pointB.y - sinValue);
CGPoint c3 = CGPointMake(square.pointB.x + cosValue, square.pointB.y + sinValue);
CGPoint c4 = CGPointMake(square.pointC.x + sinValue, square.pointC.y - cosValue);
CGPoint c5 = CGPointMake(square.pointC.x - sinValue, square.pointC.y + cosValue);
CGPoint c6 = CGPointMake(square.pointD.x + cosValue, square.pointD.y + sinValue);
CGPoint c7 = CGPointMake(square.pointD.x - cosValue, square.pointD.y - sinValue);
CGPoint c8 = CGPointMake(square.pointA.x - sinValue, square.pointA.y + cosValue);
UIBezierPath* ovalPath = [UIBezierPath bezierPath];
[ovalPath moveToPoint: square.pointA];
[ovalPath addCurveToPoint:square.pointB controlPoint1:c1 controlPoint2:c2];
[ovalPath addCurveToPoint:square.pointC controlPoint1:c3 controlPoint2:c4];
[ovalPath addCurveToPoint:square.pointD controlPoint1:c5 controlPoint2:c6];
[ovalPath addCurveToPoint:square.pointA controlPoint1:c7 controlPoint2:c8];
[ovalPath closePath];
2.小球的移动的前半圆为半圆,后半圆为半个椭圆.
_angle = atanf((desPoint.y - self.position.y)/(desPoint.x - self.position.x));
CGFloat extra1 = (self.currentRect.size.width * 2 / 5) * _factor1;
CGFloat extra2 = (self.currentRect.size.width * 2 / 5) * _factor2;
CGFloat radius1 = _currentRect.size.width/2 - extra1; //短边
CGFloat radius2 = _currentRect.size.width/2 - extra2; //长边
CGFloat offset = self.currentRect.size.width / 3.6 - extra1 / 1.8; //设置3.6 出来的弧度最像圆形
...
square.pointB = [SCCircleMath caculatePointFromAngle:_angle CirCleCenter:self.position cirCleRadius:radius1];
square.pointC = [SCCircleMath caculatePointFromAngle:_angle + M_PI_4*2 CirCleCenter:self.position cirCleRadius:radius2];
square.pointD = [SCCircleMath caculatePointFromAngle:_angle + M_PI_4*4 CirCleCenter:self.position cirCleRadius:radius1];
square.pointA = [SCCircleMath caculatePointFromAngle:_angle + M_PI_4*6 CirCleCenter:self.position cirCleRadius:radius1];
图片及公式来自以下链接:
1.谈谈iOS中粘性动画以及果冻效果的实现
2.三阶贝塞尔曲线拟合1/4圆
3.KYAnimatedPageControl
4.Workout-Book-workout-tracking-app-concept