学习计划(9) - 动画 - 贝塞尔曲线(1)

我们日常生活中用的贝塞尔曲线的地方还是比较多的,我见过的例如,自定义侧边栏的动画效果,表格的下拉效果,视图的波浪循环的效果,数据分析时的折线图,自定义TabBar的时候也会用到等等,很多自定义的想要炫酷的效果都得用到。我也一直想做一些自己喜欢的效果,所以,就腾出时间,潜心研究研究。

首先我们要扫扫盲,比较清楚的去了解它:
http://blog.csdn.net/cdnight/article/details/48468653

贝塞尔曲线包括了

一阶曲线
给定点P0、P1,线性贝塞尔曲线只是一条两点之间的直线。这条线由下式给出:


线性公式.png

二阶曲线
二次方贝塞尔曲线的路径由给定点P0、P1、P2的函数B(t)追踪:


二次方公式.png

三阶曲线
P0、P1、P2、P3 四个点在平面或在三维空间中定义了三次方贝塞尔曲线。曲线起始于 P0 走向 P1 ,并从 P2 的方向来到 P3 。一般不会经过 P1 或 P2 ;这两个点只是在那里提供方向资讯。 P0 和 P1 之间的间距,决定了曲线在转而趋进 P2 之前,走向 P1 方向的“长度有多长”。
曲线的参数形式为:


三次方公式.png

高阶曲线
n阶贝塞尔曲线可如下判断,给定点P0、p1、...、Pn,其贝塞尔曲线即


n阶曲线.jpg

WTF? 公式太抽象? 那就来看看动画吧。借用上面那篇文章的动图

曲线动态图.gif

可以看到为二阶曲线,包含了P0,P1,P2三个点.

这里有个网址比较容易的让我们能够直观方便的绘制出曲线:
https://aaaaaaaty.github.io/bezierMaker.js/playground/playground.html

为了让程序有趣点,我们来画个眉毛?(直线)

眉毛.png

当然咯,我们从简单的一步一步来。
首先是如何定义贝塞尔曲线

//先创建实例
UIBezierPath *bPath = [UIBezierPath bezierPath];

//然后我们可以设置它的颜色:
UIColor *color = hexStrColor(@"#FF8C69");
[color set];

//然后就是它的线条宽度:
bPath.lineWidth = 2.0;

基础的属性设置先用到这些。
接下来我们就要开始绘画简单的线:
线就是两个点组成的,所以我们首先设定一个起始点:
//设定屏幕中间点,这个就起始点就自己根据需求设置了。
CGPoint center = (CGPoint){kSCREENWIDTH/2,kSCREENHEIGHT/2};
将起始点移动该坐标点
[bPath moveToPoint:(CGPoint){center.x-100,center.y-50}];

//然后设定末尾的点:
[bPath addLineToPoint:(CGPoint){center.x-50,center.y-50}];

//画完记得关闭绘画的路径:
[bPath closePath];
//开始绘制之前组合出来的线
[bPath stroke];

然后我们再来画眼睛?(画实心圆)

眼睛.png
//移动到画的中心点
[bPath moveToPoint:(CGPoint){center.x-50,center.y-40}];

//画圆
/**
 *  以某个中心点画弧线
 *  @param center     指定了圆弧所在正圆的圆心点坐标
 *  @param radius     指定了圆弧所在正圆的半径
 *  @param startAngle 指定了起始弧度位置  注意: 起始与结束这里是弧度 
 *  @param endAngle   指定了结束弧度位置  
 *  @param clockwise  指定了绘制方向,以时钟方向为判断基准   看下图
 */
[bPath addArcWithCenter:(CGPoint){center.x-75,center.y-40} 
radius:10
startAngle:0
endAngle: DEGREES_TO_RADIANS(360)
clockwise:YES];

[bPath closePath];
//file 填充路径
[bPath fill];

如果设定pi的值不那么直观,我们可以用下面的宏直接填写角度
#define DEGREES_TO_RADIANS(degrees) ((M_PI * degrees)/ 180)

angle的值可以参照该图


圆 .png

嗯,我们再画个嘴(弧线)

我们画个由三个点组成的曲线。


嘴.png

不太明白的可以用
https://aaaaaaaty.github.io/bezierMaker.js/playground/playground.html
自己画一个看看:

bezier.png

可以看到,我们利用三个点绘制出我们想要的弧线。

UIBezierPath *bPathB = [UIBezierPath bezierPath];
bPathB.lineWidth = 2.0;
[bPathB moveToPoint:(CGPoint){center.x-60,center.y}];
[bPathB addQuadCurveToPoint:(CGPoint){center.x+60,center.y} controlPoint:(CGPoint){center.x,center.y+50}];
[bPathB stroke];

然后你通过上述方法会发现三个点竟然不是顺序的。是的。moveToPoint是p1,CurveToPoint是p3,而controlPoint是p2。

然后我们再利用其它的方式画个空心圆当做它的大肥脸。


脸.png
//创建CAShapeLayer对象
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.frame = CGRectMake(center.x-150, center.y-150, 300,300);//设置shapeLayer的尺寸和位置
shapeLayer.fillColor = [UIColor clearColor].CGColor;//填充颜色为ClearColor
//设置线条的宽度和颜色
shapeLayer.lineWidth = 2.0f;
shapeLayer.strokeColor = hexStrColor(@"#FF8C69").CGColor;
//创建一个圆形贝塞尔曲线
UIBezierPath *aPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0,0,300,300)];
//将贝塞尔曲线设置为CAShapeLayer的path
shapeLayer.path = aPath.CGPath;
//将shapeLayer添加到视图的layer上
[self.layer addSublayer:shapeLayer];

这个实现方式就比较简单了,就是你绘制了一个CAShapeLayer图层,然后利用它的路径进行绘制。
需要注意的是,shapeLayer的frame设置的x,y不是圆心,而是外圆开始的点。 那个宽高设不设无所谓。宽高设定由UUIBezierPath决定。

其他的绘制我们就简单的绘制一下了,毕竟我们的重点是动画。

矩形

矩形.png
绘制矩形只需要调用bezierPathWithRectF方法,然后填入参数就可以了。
UIBezierPath *rectPath = [UIBezierPath bezierPathWithRect:(CGRect){10,kSCREENHEIGHT-154,90,60}];
[rectPath setLineWidth:2.0];
[rectPath stroke];//实心的需要使用fill方法

圆角

圆角.png

生成圆角的方法:

UIBezierPath *roundedRectPath = [UIBezierPath bezierPathWithRoundedRect:(CGRect){110,kSCREENHEIGHT-154,90,60}
                                                          byRoundingCorners:UIRectCornerTopLeft
                                                                cornerRadii:(CGSize){20,20}];
[roundedRectPath setLineWidth:2.0];
[roundedRectPath fill];
cornerRadii: 表示圆角的大小咯,范围越大,圆角越圆。
奇怪的是指定了宽度就可以了,高度怎么写都不会影响。毕竟宽度可以表示半径,这高度有啥用呢

byRoundingCorners: 参数的值就是指定生成哪个方位的圆角

typedef NS_OPTIONS(NSUInteger, UIRectCorner) {
    UIRectCornerTopLeft     = 1 << 0, 左上角
    UIRectCornerTopRight    = 1 << 1, 右上角
    UIRectCornerBottomLeft  = 1 << 2, 左下角
    UIRectCornerBottomRight = 1 << 3, 右下角
    UIRectCornerAllCorners  = ~0UL 全部
};

3阶曲线

三阶曲线.png

3阶曲线设置如下图:


三阶曲线.jpeg

我们可以通过下面的动态图看一下:


三阶曲线.gif

分为起点,终点,还有两个控制点。
可以用下面的方法进行实现:

    UIBezierPath *curveRectPath = [UIBezierPath bezierPath];
    [curveRectPath moveToPoint:(CGPoint){210,kSCREENHEIGHT-124}];
    [curveRectPath addCurveToPoint:(CGPoint){290,kSCREENHEIGHT-124}
                     controlPoint1:(CGPoint){250,kSCREENHEIGHT-154}
                     controlPoint2:(CGPoint){250,kSCREENHEIGHT-94}];
    [curveRectPath setLineWidth:2.0];
    [curveRectPath stroke];

DEMO:
https://github.com/yanggenwei/GWAnimation/tree/master

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,519评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,842评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,544评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,742评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,646评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,027评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,169评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,324评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,268评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,299评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,996评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,591评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,911评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,288评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,871评论 2 341