轉 貝塞爾曲線與幀動畫

參考來自下面的文章芯义,這篇文章被轉了很多次奥洼,原文都不見了

http://www.cnblogs.com/moyunmo/p/3600091.html?utm_source=tuicool&utm_medium=referral

首先說貝塞爾的各種劃線方法

1.利用UIbezier的初始化方法,在UIView上畫bezierPath

a.利用UIbezier的初始化方法恨搓,可以創(chuàng)建出圓形家乘,矩形,圓角矩形

b.使用moveToPoint設置起始點精置,使用addLineToPoint增加點

下面的類繼承于UIView,當此CircleView添加到父視圖上時锣杂,會自動調用drawRect方法

[objc]view plaincopy

//弧度轉角度

#define?RADIANS_TO_DEGREES(radians)?((radians)?*?(180.0?/?M_PI))

//角度轉弧度

#define?DEGREES_TO_RADIANS(angle)?((angle)?/?180.0?*?M_PI)

#import?"CircleView.h"

@implementationCircleView

-(void)drawRect:(CGRect)rect

{

//1.圓形

UIBezierPath*bPath?=?[UIBezierPathbezierPathWithArcCenter:CGPointMake(300,300)radius:50

startAngle:?DEGREES_TO_RADIANS(135)endAngle:M_PI*2clockwise:YES];

//設置顏色

[[UIColorredColor]setStroke];

//設置線寬

[bPathsetLineWidth:5];

//繪制

[bPathstroke];

//2.橢圓

UIBezierPath*ovalPath?=?[UIBezierPathbezierPathWithOvalInRect:CGRectMake(200,150,100,200)];

[ovalPathsetLineWidth:5];

[ovalPathstroke];

//3.矩形

UIBezierPath*myBezierPath?=?[UIBezierPathbezierPathWithRect:CGRectMake(20,20,100,50)];

[[UIColorwhiteColor]setStroke];

[myBezierPathsetLineWidth:5];

[myBezierPathstroke];

//4.圓角矩形

//UIRectCorner可以設置?哪幾個角是圓角脂倦,其他不變

UIBezierPath*tBPath?=?[UIBezierPathbezierPathWithRoundedRect:CGRectMake(220,20,100,100)

byRoundingCorners:UIRectCornerTopLeft?|?UIRectCornerBottomLeftcornerRadii:CGSizeMake(20,20)];

[[UIColorgreenColor]setStroke];

[tBPathsetLineWidth:5];

[tBPathstroke];

//5.通過添加點生成任意圖形

UIBezierPath*?aPath?=?[UIBezierPathbezierPath];

aPath.lineWidth=15.0;

aPath.lineCapStyle=?kCGLineCapButt;//線條終點

//round?圓形

//butt?平的?默認值?把線連接到精準的終點

//Square?平的番宁,會把線延伸到終點再加上線寬的一半

aPath.lineJoinStyle=?kCGLineJoinBevel;//拐點處理

//bevel?斜角斜面,角的外側是平的不圓滑

//miter?斜接?角的外側是尖的

//round?圓角

//這是起點

[aPathmoveToPoint:CGPointMake(100.0,200.0)];

//添加點

[aPathaddLineToPoint:CGPointMake(200.0,240.0)];

[aPathaddLineToPoint:CGPointMake(160,340)];

[aPathaddLineToPoint:CGPointMake(40.0,340)];

[aPathaddLineToPoint:CGPointMake(10.0,240.0)];

[aPathclosePath];//第五條線通過調用closePath方法得到的

[aPathstroke];//Draws?line?根據坐標點連線

}

@end

2.二次曲線和三次曲線

盜圖兩張赖阻,他們解釋了控制點是怎么回事

劃線方法很簡單

二次曲線

[objc]view plaincopy

//創(chuàng)建一條貝塞爾

UIBezierPath*?aPath?=?[UIBezierPathbezierPath];

aPath.lineWidth=5.0;//寬度

aPath.lineCapStyle=?kCGLineCapRound;//線條拐角

aPath.lineJoinStyle=?kCGLineJoinRound;//終點處理

//起始點

[aPathmoveToPoint:CGPointMake(20,100)];

//添加兩個控制點

[aPathaddQuadCurveToPoint:CGPointMake(220,100)controlPoint:CGPointMake(170,0)];

//劃線

[aPathstroke];

三次曲線

[objc]view plaincopy

//三次曲線

UIBezierPath*?bPath?=?[UIBezierPathbezierPath];

bPath.lineWidth=5.0;

bPath.lineCapStyle=?kCGLineCapRound;//線條拐角

bPath.lineJoinStyle=?kCGLineCapRound;//終點處理

//起始點

[bPathmoveToPoint:CGPointMake(20,250)];

//添加兩個控制點

[bPathaddCurveToPoint:CGPointMake(350,250)controlPoint1:CGPointMake(310,200)controlPoint2:CGPointMake(210,400)];

[bPathstroke];

3.了解一下底層的Core Graphics

這篇文章說的夠了

http://www.mamicode.com/info-detail-841887.html

[objc]view plaincopy

-(void)drawRect:(CGRect)rect

{

//?Create?the?path?data

//創(chuàng)建路徑時間

CGMutablePathRef?cgPath?=?CGPathCreateMutable();

//cgPath的畫圖接口

//給一個cgPath里面添加了多個樣式蝶押,圓和橢圓會發(fā)生關聯(lián)

//兩個橢圓互不影響

CGPathAddEllipseInRect(cgPath,NULL,?CGRectMake(100,100,50,100));

CGPathAddEllipseInRect(cgPath,NULL,?CGRectMake(250,250,100,50));

//矩形

CGPathAddRect(cgPath,NULL,?CGRectMake(200,500,30,100));

//????圓形

//????CGPathAddArc(cgPath,?NULL,?120,?400,?100,?0,?M_PI*2,?YES);

//下面兩句要搭配,先有起點

CGPathMoveToPoint(cgPath,NULL,200,300);

//加一段弧

CGPathAddArcToPoint(cgPath,NULL,320,250,?DEGREES_TO_RADIANS(150),?M_PI*2,50);

//把CGPath賦給貝塞爾曲線

UIBezierPath*?aPath?=?[UIBezierPathbezierPath];

aPath.CGPath=?cgPath;

aPath.usesEvenOddFillRule=YES;

//并不在ARC的管理范圍之內政供。所以需要手動釋放對象播聪,釋放cgPath

CGPathRelease(cgPath);

//劃線

[[UIColorredColor]setStroke];

[aPathsetLineWidth:5];

[aPathstroke];

}

4.通過shapeLayer畫線

這樣就不用去UIView的drawRect方法里面畫圖了朽基,也就是可以在ViewController里面繪制了

[objc]view plaincopy

//ShapeLayer

-(void)layerAnimation

{

//貝塞爾畫圓

UIBezierPath*path?=?[UIBezierPathbezierPathWithArcCenter:CGPointMake(100,100)radius:100startAngle:0endAngle:M_PIclockwise:NO];

//初始化shapeLayer

self.myShapeLayer=?[CAShapeLayerlayer];

_myShapeLayer.frame=?_redView.bounds;

_myShapeLayer.strokeColor=?[UIColorgreenColor].CGColor;//邊沿線色

_myShapeLayer.fillColor=?[UIColorgrayColor].CGColor;//填充色

_myShapeLayer.lineJoin=?kCALineJoinMiter;//線拐點的類型

_myShapeLayer.lineCap=?kCALineCapSquare;//線終點

//從貝塞爾曲線獲得形狀

_myShapeLayer.path=?path.CGPath;

//線條寬度

_myShapeLayer.lineWidth=10;

//起始和終止

_myShapeLayer.strokeStart=0.0;

_myShapeLayer.strokeEnd=1.0;

//將layer添加進圖層

[self.redView.layeraddSublayer:_myShapeLayer];

}

二布隔、關鍵幀動畫

[objc]view plaincopy

//關鍵幀動畫

-(void)layerKeyFrameAnimation

{

//畫一個path

UIBezierPath*path?=?[UIBezierPathbezierPath];

[pathmoveToPoint:CGPointMake(-40,100)];

[pathaddLineToPoint:CGPointMake(360,100)];

[pathaddLineToPoint:CGPointMake(360,200)];

[pathaddLineToPoint:CGPointMake(-40,200)];

[pathaddLineToPoint:CGPointMake(-40,300)];

[pathaddLineToPoint:CGPointMake(360,300)];

//幾個固定點

NSValue*orginalValue?=?[NSValuevalueWithCGPoint:self.redView.layer.position];

NSValue*value_1=?[NSValuevalueWithCGPoint:CGPointMake(300,300)];

NSValue*value_2=?[NSValuevalueWithCGPoint:CGPointMake(400,300)];

NSValue*value_3=?[NSValuevalueWithCGPoint:CGPointMake(400,400)];

//變動的屬性,keyPath后面跟的屬性是CALayer的屬性

CAKeyframeAnimation*keyFA?=?[CAKeyframeAnimationanimationWithKeyPath:@"position"];

//value數組,放所有位置信息稼虎,如果設置path衅檀,此項會被忽略

keyFA.values=?@[orginalValue,value_1,value_2,value_3];

//動畫路徑

//????keyFA.path?=?path.CGPath;

//該屬性是一個數組,用以指定每個子路徑(AB,BC,CD)的時間霎俩。如果你沒有顯式地對keyTimes進行設置哀军,則系統(tǒng)會默認每條子路徑的時間為:ti=duration/(幀數),即每條子路徑的duration相等

keyFA.keyTimes=?@[@(0.0),@(0.5),@(0.9),@(2)];

//動畫總時間

keyFA.duration=5.0f;

//重復次數打却,小于0無限重復

keyFA.repeatCount=10;

/*

這個屬性用以指定時間函數杉适,類似于運動的加速度

kCAMediaTimingFunctionLinear//線性

kCAMediaTimingFunctionEaseIn//淡入

kCAMediaTimingFunctionEaseOut//淡出

kCAMediaTimingFunctionEaseInEaseOut//淡入淡出

kCAMediaTimingFunctionDefault//默認

*/

keyFA.timingFunction=?[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionLinear];

/*

fillMode的作用就是決定當前對象過了非active時間段的行為.?比如動畫開始之前,動畫結束之后。如果是一個動畫CAAnimation,則需要將其removedOnCompletion設置為NO,要不然fillMode不起作用.

下面來講各個fillMode的意義

kCAFillModeRemoved?這個是默認值,也就是說當動畫開始前和動畫結束后,動畫對layer都沒有影響,動畫結束后,layer會恢復到之前的狀態(tài)

kCAFillModeForwards?當動畫結束后,layer會一直保持著動畫最后的狀態(tài)

kCAFillModeBackwards?這個和kCAFillModeForwards是相對的,就是在動畫開始前,你只要將動畫加入了一個layer,layer便立即進入動畫的初始狀態(tài)并等待動畫開始.你可以這樣設定測試代碼,將一個動畫加入一個layer的時候延遲5秒執(zhí)行.然后就會發(fā)現在動畫沒有開始的時候,只要動畫被加入了layer,layer便處于動畫初始狀態(tài)

kCAFillModeBoth?理解了上面兩個,這個就很好理解了,這個其實就是上面兩個的合成.動畫加入后開始之前,layer便處于動畫初始狀態(tài),動畫結束后layer保持動畫最后的狀態(tài).

//添加動畫

*/

keyFA.fillMode=?kCAFillModeForwards;

/*

在關鍵幀動畫中還有一個非常重要的參數,那便是calculationMode,計算模式.該屬性決定了物體在每個子路徑下是跳著走還是勻速走柳击,跟timeFunctions屬性有點類似

其主要針對的是每一幀的內容為一個座標點的情況,也就是對anchorPoint?和?position?進行的動畫.當在平面座標系中有多個離散的點的時候,可以是離散的,也可以直線相連后進行插值計算,也可以使用圓滑的曲線將他們相連后進行插值計算.?calculationMode目前提供如下幾種模式

kCAAnimationLinear?calculationMode的默認值,表示當關鍵幀為座標點的時候,關鍵幀之間直接直線相連進行插值計算;

kCAAnimationDiscrete?離散的,就是不進行插值計算,所有關鍵幀直接逐個進行顯示;

kCAAnimationPaced?使得動畫均勻進行,而不是按keyTimes設置的或者按關鍵幀平分時間,此時keyTimes和timingFunctions無效;

kCAAnimationCubic?對關鍵幀為座標點的關鍵幀進行圓滑曲線相連后插值計算,對于曲線的形狀還可以通過tensionValues,continuityValues,biasValues來進行調整自定義,這里的數學原理是Kochanek–Bartels?spline,這里的主要目的是使得運行的軌跡變得圓滑;

kCAAnimationCubicPaced?看這個名字就知道和kCAAnimationCubic有一定聯(lián)系,其實就是在kCAAnimationCubic的基礎上使得動畫運行變得均勻,就是系統(tǒng)時間內運動的距離相同,此時keyTimes以及timingFunctions也是無效的.

*/

keyFA.calculationMode=?kCAAnimationPaced;

//旋轉的模式,auto就是沿著切線方向動猿推,autoReverse就是轉180度沿著切線動

keyFA.rotationMode=?kCAAnimationRotateAuto;

//結束后是否移除動畫

keyFrameAnimation.removedOnCompletion=NO;

//添加動畫

[self.redView.layeraddAnimation:keyFAforKey:@""];

}

這里有個泡泡動畫的demo,結合了貝塞爾曲線和幀動畫捌肴,很精致

https://github.com/bnb173yjx/BubbleAnimationDemo

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末蹬叭,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子状知,更是在濱河造成了極大的恐慌秽五,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件饥悴,死亡現場離奇詭異坦喘,居然都是意外死亡,警方通過查閱死者的電腦和手機西设,發(fā)現死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門起宽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人济榨,你說我怎么就攤上這事坯沪。” “怎么了擒滑?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵腐晾,是天一觀的道長叉弦。 經常有香客問我,道長藻糖,這世上最難降的妖魔是什么淹冰? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮巨柒,結果婚禮上樱拴,老公的妹妹穿的比我還像新娘。我一直安慰自己洋满,他們只是感情好晶乔,可當我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著牺勾,像睡著了一般正罢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上驻民,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天翻具,我揣著相機與錄音,去河邊找鬼回还。 笑死裆泳,一個胖子當著我的面吹牛,可吹牛的內容都是我干的柠硕。 我是一名探鬼主播工禾,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼仅叫!你這毒婦竟也來了帜篇?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤诫咱,失蹤者是張志新(化名)和其女友劉穎笙隙,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體坎缭,經...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡竟痰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了掏呼。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坏快。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖憎夷,靈堂內的尸體忽然破棺而出莽鸿,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布祥得,位于F島的核電站兔沃,受9級特大地震影響,放射性物質發(fā)生泄漏级及。R本人自食惡果不足惜乒疏,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望饮焦。 院中可真熱鬧怕吴,春花似錦、人聲如沸县踢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽殿雪。三九已至暇咆,卻和暖如春锋爪,著一層夾襖步出監(jiān)牢的瞬間丙曙,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工其骄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留亏镰,地道東北人。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓拯爽,卻偏偏與公主長得像索抓,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子毯炮,可洞房花燭夜當晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內容