使用CADisplayLink实现果冻效果动画

原文地址:http://www.cocoachina.com/ios/20150320/11382.html

CADisplayLink是什么

根据Apple的doc:

A CADisplayLink object is a timer object that allows your application to synchronize its drawing to the refresh rate of the display.

比起NSTimer,CADisplayLink可以确保系统渲染每一帧的时候我们的方法都被调用,从而保证了动画的流畅性。

Demo

我们希望在animate一个view的时候给它加上果冻效果: 

demo.gif

我们会把所有的逻辑都封装到一个BlockView里,在这个view里首先申明一个property:

1
@property (strong, nonatomic) CADisplayLink *displayLink;

在动画开始的时候,初始化displayLink,指定tick方法:

1
2
3
4
5
6
7
8
- (void)startAnimation
{
     if  (self.displayLink == nil) {
         self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(tick:)];
         [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop]
                                forMode:NSDefaultRunLoopMode];
     }
}

动画结束的时候invalidate displayLink:

1
2
3
4
5
- (void)completeAnimation
{
     [self.displayLink invalidate];
     self.displayLink = nil;
}

每个tick中,我们需要根据当前的位置重绘边缘,所以只需调用setNeedsDisplay即可:

1
2
3
4
- (void)tick:(CADisplayLink *)displayLink
{
     [self setNeedsDisplay];
}

在drawRect中,我们计算当前动画的progress,然后进行绘制。需要注意的是,我们需要通过self.layer.presentationLayer来获取动画过程中的位置信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- (void)drawRect:(CGRect)rect
{
     CALayer *layer = self.layer.presentationLayer;
     CGFloat progress = 1 - (layer.position.y - self.to) / (self.from - self.to);
     CGFloat height = CGRectGetHeight(rect);
     CGFloat deltaHeight = height / 2 * (0.5 - fabs(progress - 0.5));
     CGPoint topLeft = CGPointMake(0, deltaHeight);
     CGPoint topRight = CGPointMake(CGRectGetWidth(rect), deltaHeight);
     CGPoint bottomLeft = CGPointMake(0, height);
     CGPoint bottomRight = CGPointMake(CGRectGetWidth(rect), height);
     UIBezierPath* path = [UIBezierPath bezierPath];
     [[UIColor blueColor] setFill];
     [path moveToPoint:topLeft];
     [path addQuadCurveToPoint:topRight controlPoint:CGPointMake(CGRectGetMidX(rect), 0)];
     [path addLineToPoint:bottomRight];
     [path addQuadCurveToPoint:bottomLeft controlPoint:CGPointMake(CGRectGetMidX(rect), height - deltaHeight)];
     [path closePath];
     [path fill];
}

最后,我们只需要这样animate这个BlockView:

1
2
3
4
5
6
     [self.blockView startAnimationFrom:from to:to];
     [UIView animateWithDuration:1 delay:0 usingSpringWithDamping:0.85 initialSpringVelocity:0 options:0 animations:^{
         self.blockView.center = CGPointMake(self.blockView.center.x, to);
     } completion:^(BOOL finished) {
         [self.blockView completeAnimation];
     }];

Demo Project

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值