iOS - 用 UIBezierPath 实现果冻效果
最近在网上看到一个很酷的下拉刷新效果(http://iostuts.io/2015/10/17/elastic-bounce-using-uibezierpath-and-pan-gesture/)。自己试着实现了一下其中的果冻回弹效果。
效果

DEMO
由于文笔不太好-.- ,建议先下载demo,再结合下面的分析,会好理解点。地址https://github.com/Resory/RYCuteView
逻辑
下图p1,蓝色部分图形是一个CAShapeLayer,他的形状由UIBezierPath的路径组成的。
这个路径是由r1,r2,r3,r4,r5这5个红点确定的。其中r1,r2,r3,r4都是不动点,
唯一可以动的是r5点。根据上面的动态图可以看出,
CAShapeLayer的形状是随着r5红点的移动而相应变化的,所以只要获得r5的坐标变化就可以用UIBezierPath做出相应的路径,然后就可以形成相应的形状。

实现
初始化CAShapeLayer
|
1
2
3
4
5
6
|
- (void)configShapeLayer{ _shapeLayer = [CAShapeLayer layer]; _shapeLayer.fillColor = [UIColor colorWithRed:57/255.0 green:67/255.0 blue:89/255.0 alpha:1.0].CGColor; [self.layer addSublayer:_shapeLayer];} |
初始化r5点
|
1
2
3
4
5
6
7
8
9
|
- (void)configCurveView{ // _curveView就是r5点 _curveX = SYS_DEVICE_WIDTH/2.0; // r5点x坐标 _curveY = MIN_HEIGHT; // r5点y坐标 _curveView = [[UIView alloc] initWithFrame:CGRectMake(_curveX, _curveY, 3, 3)]; _curveView.backgroundColor = [UIColor redColor]; [self addSubview:_curveView];} |
添加移动手势&CADisplayLink
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
- (void)configAction{ _mHeight = 100; // 手势移动时相对高度 _isAnimating = NO; // 是否处于动效状态 // 手势 UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanAction:)]; self.userInteractionEnabled = YES; [self addGestureRecognizer:pan]; // calculatePath方法是算出在运行期间_curveView的坐标,从而确定_shapeLayer的形状 _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(calculatePath)]; [_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; // 在手势结束的时候才调用calculatePath方法,所以一开始是暂停的 _displayLink.paused = YES; } |
手势解析
手势移动时,r5红点跟着手势移动,_shapeLayer则根据r5的坐标来扩大自己的区域
手势结束时,r5红点通过UIView的动画方法来改变r5的坐标,同时_shapeLayer根据r5的坐标缩小自己的区域并最终返回原形。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
- (void)handlePanAction:(UIPanGestureRecognizer *)pan{ if(!_isAnimating) { if(pan.state == UIGestureRecognizerStateChanged) { // 手势移动时,_shapeLayer跟着手势向下扩大区域 CGPoint point = [pan translationInView:self]; // 这部分代码使r5红点跟着手势走 _mHeight = point.y*0.7 + MIN_HEIGHT; _curveX = SYS_DEVICE_WIDTH/2.0 + point.x; _curveY = _mHeight > MIN_HEIGHT ? _mHeight : MIN_HEIGHT; _curveView.frame = CGRectMake(_curveX, _curveY, _curveView.frame.size.width, _curveView.frame.size.height); // 根据r5坐标,更新_shapeLayer形状 [self updateShapeLayerPath]; } else if (pan.state == UIGestureRecognizerStateCancelled || pan.state == UIGestureRecognizerStateEnded || pan.state == UIGestureRecognizerStateFailed) { // 手势结束时,_shapeLayer返回原状并产生弹簧动效 _isAnimating = YES; _displayLink.paused = NO; //开启displaylink,会执行方法calculatePath. // 弹簧动效 [UIView animateWithDuration:1.0 delay:0.0 usingSpringWithDamping:0.5 initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ // 曲线点(r5点)是一个view.所以在block中有弹簧效果.然后根据他的动效路径,在calculatePath中计算弹性图形的形状 _curveView.frame = CGRectMake(SYS_DEVICE_WIDTH/2.0, MIN_HEIGHT, 3, 3); } completion:^(BOOL finished) { if(finished) { _displayLink.paused = YES; _isAnimating = NO; } }]; } }} |
根据r5的位置,更新_shapeLayer形状
|
1
2
3
4
5
6
7
8
9
10
11
12
|
- (void)updateShapeLayerPath{ // 更新_shapeLayer形状 UIBezierPath *tPath = [UIBezierPath bezierPath]; [tPath moveToPoint:CGPointMake(0, 0)]; //r1点 [tPath addLineToPoint:CGPointMake(SYS_DEVICE_WIDTH, 0)];// r2点 [tPath addLineToPoint:CGPointMake(SYS_DEVICE_WIDTH, MIN_HEIGHT)]; //r4点 [tPath addQuadCurveToPoint:CGPointMake(0, MIN_HEIGHT) controlPoint:CGPointMake(_curveX, _curveY)]; // r3,r4,r5确定的一个弧线 [tPath closePath]; _shapeLayer.path = tPath.CGPath;} |
计算弹簧效果坐标
|
1
2
3
4
5
6
7
8
|
- (void)calculatePath{ // 由于手势结束时,r5执行了一个UIView的弹簧动画,把这个过程的坐标记录下来,并相应的画出_shapeLayer形状 CALayer *layer = _curveView.layer.presentationLayer; _curveX = layer.position.x; _curveY = layer.position.y; [self updateShapeLayerPath];} |
末
r5点的作用非常重要,因为直接对CAShapeLayer实现动效不太好实现。所以通过对r5点实现弹簧动效,记录r5点的坐标,再用UIBezierPath形成路径,最后赋予CAShapeLayer,间接的完成了CAShapeLayer的弹簧动效。
链接:
Elastic view animation using UIBezierPath
iOS - 用 UIBezierPath 实现果冻效果的更多相关文章
- CADisplayLink+弹簧动画实现果冻效果
项目中在Tabbar中间的按钮要从底部弹出视图并有果冻效果,在CocoaChina中找了一篇博客用 UIBezierPath 实现果冻效果,github,自己就按着上面的demo修改了一下( 之前也是 ...
- iOS开发——图形编程OC篇&粘性动画以及果冻效果
粘性动画以及果冻效果 在最近做个一个自定义PageControl——KYAnimatedPageControl中,我实现了CALayer的形变动画以及CALayer的弹性动画,效果先过目: 先做个提纲 ...
- 谈谈iOS中粘性动画以及果冻效果的实现
在最近做个一个自定义PageControl——KYAnimatedPageControl中,我实现了CALayer的形变动画以及CALayer的弹性动画,效果先过目: https://github.c ...
- 转:谈谈iOS中粘性动画以及果冻效果的实现
在最近做个一个自定义PageControl——KYAnimatedPageControl中,我实现了CALayer的形变动画以及CALayer的弹性动画,效果先过目: 先做个提纲: 第一个分享的主题是 ...
- iOS 之UIBezierPath
代码地址如下:http://www.demodashi.com/demo/11602.html 在之前的文章中,由于用到过UIBezierPath这个类,所以这里就对这个类进行简单的记录一下,方便自己 ...
- XE8 for iOS 状态栏的几种效果
XE8 实现 iOS 状态栏的几种效果: 一.状态栏底色: 开一个新工程. 设定 Fill.Color 颜色属性. 设定 Fill.Kind = Solid. 无需修改任何官方源码. 二.隐藏状态栏( ...
- ios点击产生波纹效果
ios点击产生波纹效果 by 伍雪颖 - (void)viewDidLoad { [super viewDidLoad]; RippleView = [[UIView alloc] initWithF ...
- iOS CAReplicatorLayer 实现脉冲动画效果
iOS CAReplicatorLayer 实现脉冲动画效果 效果图 脉冲数量.速度.半径.透明度.渐变颜色.方向等都可以设置.可以用于地图标注(Annotation).按钮长按动画效果(例如录音按钮 ...
- xmarin live player 连接 IOS以及安卓实现实时效果查看
原文:xmarin live player 连接 IOS以及安卓实现实时效果查看 在之前有介绍过xamarin 单独IOS项目开发的运行环境搭建,但是这段时间我看到了xmarin forms 3.0 ...
随机推荐
- svn(http)
对于有些公司的运维 他确实很垃圾 所以 你一定要谨记这一点!!!
- 【读书笔记】iOS-反溃网络信息改善用户体验
一,iOS6表视图刷新控件的使用. 二,使用等待指示器控件. 三,使用网络等待指示器. 四,使用MBProgressHUD等待指示器. 参考资料:<iOS网络编程与云端应用-最佳实践>
- iOS 远程推送通知
1.什么是推送通知 在某些特殊情况下,应用程序被动收到的以不同种界面形式出现的提醒信息 推送通知的作用:可以让不在前台运行的app通知app发生了改变 iOS中得推送通知种类 远程推送通知(Remot ...
- zend studio 8 修字体和大小
第一步:进入设置窗口 windows -> preferences 第二步:进入修改字体的选项卡. General -> Appearance -> Colors and ...
- mysql 命令行操作入门(详细讲解版)
之前分享过多次Mysql主题,今天继续分享mysql命令行入门 1. 那么多mysql客户端工具,为何要分享命令行操作? -快捷.简单.方便 -在没有客户端的情况下怎么办 -如果是mysql未开启 ...
- w3wp.exe(IIS ) CPU 占用 100% 的常见原因及解决办法
对于IIS 管理员来说,经常会碰到 Web 服务器 CPU 占用 100% 的情况,以下是个人的日常工作总结和一些解决办法,主要用来剖析 w3wp.exe(IIS ) 占用 CPU 100% 的一些 ...
- Sql Server之旅——第六站 使用winHex利器加深理解数据页
这篇我来介绍一个winhex利器,这个工具网上有介绍,用途大着呢,可以用来玩数据修复,恢复删除文件等等....它能够将一个file解析成 hex形式,这样你就可以对hex进行修改,然后你就可以看到修复 ...
- Javascript之旅——第十一站:原型也不好理解?
写到这篇,我的js系列也快接近尾声了,所以这个系列不会遗留js来实现面向对象的核心——原型,有些人说原型不好理解,其实嘛,要想系统 的理解原型,最便捷的方式就是看看经典的书,少看些博客,博客这东西只是 ...
- Java并发之CyclicBarrier 可重用同步工具类
package com.thread.test.thread; import java.util.Random; import java.util.concurrent.*; /** * Cyclic ...
- Servlet/JSP-05 Cookie
一. 问题? HTTP协议是一种无状态协议,服务器本身无法识别出哪些请求是同一个浏览器发出的,浏览器的每一次请求都是独立的.现实业务中服务器有时候需要识别来自同一个浏览器的一系列请求,例如购物车,登录 ...