參考來自下面的文章芯义,這篇文章被轉了很多次奥洼,原文都不見了
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