iOS开发 - 用 UIBezierPath 实现果冻效果
来源:互联网 发布:sql case when 出汉字 编辑:程序博客网 时间:2024/04/29 03:49
转载地址:http://www.cocoachina.com/ios/20151231/14823.html
最近在网上看到一个很酷的下拉刷新效果(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
- (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点
- (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
- (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的坐标缩小自己的区域并最终返回原形。
- (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形状
- (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;
}
计算弹簧效果坐标
- (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的弹簧动效。
- iOS开发 - 用 UIBezierPath 实现果冻效果
- ios 用 UIBezierPath 实现果冻效果
- iOS开发:粘性动画以及果冻效果的实现
- iOS开发:粘性动画以及果冻效果的实现
- 果冻回弹效果 拉刷新效果 UIBezierPath
- 谈谈iOS中粘性动画以及果冻效果的实现
- IOS粘性动画以及果冻效果的实现
- 谈谈iOS中粘性动画以及果冻效果的实现
- 谈谈iOS中粘性动画以及果冻效果的实现
- 谈谈iOS中粘性动画以及果冻效果的实现
- iOS 仿 UC 浏览器个人中心 (下拉实现果冻效果)
- iOS 仿 UC 浏览器个人中心 (下拉实现果冻效果)
- animation 实现果冻突出效果
- jq实现果冻抖动效果
- iOS CAShapeLayer + UIBezierPath 实现震动条调效果
- 【iOS开发】UIBezierPath
- cocos2dx 实现果冻,刀光等效果
- 使用CADisplayLink实现果冻效果动画
- 算法分析与设计-05-棋盘覆盖问题算法
- 23中开发模式之单例模式
- 宏定义
- 转载的关于C++如何提高效率的方法
- 98% 的开发者在工作中使用了开源软件
- iOS开发 - 用 UIBezierPath 实现果冻效果
- expect 实现 自动打包和提交代码到github
- Margin的垂直外边距问题
- canvas开发专题-第一天
- 第4课java
- 从一副52张的牌中,选出四张,然后计算它们的和。其中,J、Q、K和A分别表示11、12、13和1。编写程序显示得到的和为24的选牌次数,并显示选出的牌。
- 第二十讲 项目 反转数组,成绩处理等
- Java基础学习总结(78)——Java main方法深入研究学习
- 原生JS向本地写入和保存数据