由於項目中要加入一個類似於購物車的拋物線動畫的需求,開始研究了下貝塞爾曲線的相關內容,首先了解下UIBezierPath基礎。
UIBezierPath基礎
使用UIBezierPath類可以創建基於矢量的路徑,這個類在UIKit中。此類是Core Graphics框架關於path的一個封裝。使用此類可以定義簡單的形狀,如橢圓或者矩形,或者有多個直線和曲線段組成的形狀。
使用
UIBezierPath的使用
- 創建UIBezierPath對象;
- 調用moveToPoint設置初始路徑的地點;
- 添加line(線)或者curve(曲線)去定義一個或者多個subpaths(子路徑);
- 設置UIBezierPath對象繪製的相關屬性,例如填充顏色、填充樣式、畫筆屬性等。
創建UIBezierPath方法
+(instancetype)bezierPath;
+(instancetype)bezierPathWithRect:(CGRect)rect;
+(instancetype)bezierPathWithOvalInRect:(CGRect)rect;
+(instancetype)bezierPathWithRoundedRect:(CGRect)rect
cornerRadius:(CGFloat)cornerRadius;
+(instancetype)bezierPathWithRoundedRect:(CGRect)rect
byRoundingCorners:(UIRectCorner)corners
cornerRadii:(CGSize)cornerRadii;
+(instancetype)bezierPathWithArcCenter:(CGPoint)center
radius:(CGFloat)radius
startAngle:(CGFloat)startAngle
endAngle:(CGFloat)endAngle
clockwise:(BOOL)clockwise;
+(instancetype)bezierPathWithCGPath:(CGPathRef)CGPath;
通過上面這些工廠方法可以創建任意類型的的圖形,下面具體介紹下它們的用途
1.+(instancetype)bezierPath 創建UIBezierPath對象,根據我們的需求畫任意樣式的圖形;
2.+(instancetype)bezierPathWithRect:(CGRect)rect 根據一個矩形畫貝塞爾曲線;
3.+(instancetype)bezierPathWithOvalInRect:(CGRect)rect 根據矩形畫內切曲線,例如圓或者橢圓;
4.+(instancetype)bezierPathWithRoundedRect:(CGRect)rect
cornerRadius:(CGFloat)cornerRadius 根據矩形畫帶圓角的矩形;
5.+(instancetype)bezierPathWithRoundedRect:(CGRect)rect
byRoundingCorners:(UIRectCorner)corners
cornerRadii:(CGSize)cornerRadii 根據矩形制定一個角爲圓角;
6.+(instancetype)bezierPathWithArcCenter:(CGPoint)center
radius:(CGFloat)radius
startAngle:(CGFloat)startAngle
endAngle:(CGFloat)endAngle
clockwise:(BOOL)clockwise這個方法用來畫弧,五個參數分別代表弧線中心點的座標、弧線所在圓的半徑、弧線開始的角度、弧線結束的角度、是否順時針畫弧線條。
Ps:我們需要在- (void)drawRect:(CGRect)rect中創建UIBezierPath對象並且調用以上工廠方法,因爲在drawRect方法中我們纔可以獲取到上下文。
畫直線
// 創建path
UIBezierPath *path = [UIBezierPath bezierPath];
//添加路徑(起點(100,100)到終點(200,100)的線段)到path
[path moveToPoint:CGPointMake(100 , 100)];
[path addLineToPoint:CGPointMake(200, 100)];
//將path繪製出來
[path stroke];
效果圖:
畫三角形
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(20, 20)];
[path addLineToPoint:CGPointMake(self.frame.size.width - 45, 20)];
[path addLineToPoint:CGPointMake(self.frame.size.width - 45, self.frame.size.height - 20)];
[path closePath];
//設置描邊寬度
path.lineWidth = 2;
//設置填充顏色
UIColor *fillColor = [UIColor cyanColor];
[fillColor set];
//填充
[path fill];
//設置畫筆顏色
UIColor *strokeColor = [UIColor orangeColor];
[strokeColor set];
//描邊
[path stroke];
Ps:注意填充顏色、畫筆顏色的順序,先設置填充顏色再設置畫筆顏色。
效果圖如下:
畫矩形
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(20, 20, self.frame.size.width - 40, self.frame.size.height - 40)];
path.lineCapStyle = kCGLineCapRound; //線條拐角
path.lineJoinStyle = kCGLineJoinBevel; //終點處理
path.lineWidth = 2;
//設置填充顏色
UIColor *fillColor = [UIColor yellowColor];
[fillColor set];
//填充
[path fill];
//設置畫筆顏色
UIColor *strokeColor = [UIColor orangeColor];
[strokeColor set];
//描邊
[path stroke];
代碼解釋:
1.lineCapStyle屬性是設置線條拐角帽的樣式
kCGLineCapButt 默認的
kCGLineCapRound 輕微圓角
kCGLineCapSquare 正方形
2.lineJoinStyle屬性是設置兩條線連接點的樣式
kCGLineJoinMiter 默認的表示斜接
kCGLineJoinRound 圓滑銜接
kCGLineJoinBevel 斜角連接
效果圖:
畫圓
//注意需要傳入正方形
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(60, 60, 150, 150)];
path.lineWidth = 2;
//設置填充顏色
UIColor *fillColor = [UIColor greenColor];
[fillColor set];
//填充
[path fill];
//設置畫筆顏色
UIColor *strokeColor = [UIColor orangeColor];
[strokeColor set];
//描邊
[path stroke];
Ps:
使用+ bezierPathWithOvalInRect創建UIBezierPath對象,當rect參數傳入正方形的時候,畫出來的是圓形,若rect參數不是正方,畫出來是橢圓。
效果圖:
畫橢圓
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(20, 20, 40, 60)];
path.lineWidth = 2;
//設置填充顏色
UIColor *fillColor = [UIColor magentaColor];
[fillColor set];
//填充
[path fill];
//設置畫筆顏色
UIColor *strokeColor = [UIColor orangeColor];
[strokeColor set];
//描邊
[path stroke];
使用bezierPathWithOvalInRect畫橢圓,rect參數不傳正方形,畫出來的就是橢圓。
效果圖如下:
畫帶圓角的矩形
+(instancetype)bezierPathWithRoundedRect:(CGRect)rect
cornerRadius:(CGFloat)cornerRadius;
+(instancetype)bezierPathWithRoundedRect:(CGRect)rect
byRoundingCorners:(UIRectCorner)corners
cornerRadii:(CGSize)cornerRadii;
第一個方法可以畫帶圓角的矩形,rect參數是矩形,cornerRadius參數是圓角的大小;第二個方法可以制定某一個角畫成圓角。
首先來畫四個角都是圓角的
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(20, 20, 40, 40) cornerRadius:20];
//設置填充顏色
UIColor *fillColor = [UIColor orangeColor];
[fillColor set];
//填充
[path fill];
//設置畫筆顏色
UIColor *strokeColor = [UIColor blueColor];
[strokeColor set];
//描邊
[path stroke];
效果圖如下:
接下來畫右上角是圓角的
//制定右上角爲圓角
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(20, 20, self.frame.size.width - 40, self.frame.size.height - 40) byRoundingCorners:UIRectCornerTopRight cornerRadii:CGSizeMake(20, 20)];
//設置填充顏色
UIColor *fillColor = [UIColor orangeColor];
[fillColor set];
//填充
[path fill];
//設置畫筆顏色
UIColor *strokeColor = [UIColor blueColor];
[strokeColor set];
//描邊
[path stroke];
代碼解釋:第一個參數傳矩形,第二個參數制定哪個角爲圓角,第三個參數指定水平和垂直方向半徑的大小。
效果圖如下:
畫弧
下圖爲弧線的參考系
#define kDegreesToRadians(degrees) ((M_PI * degrees)/ 180)
CGPoint centerPoint = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2);
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:centerPoint radius:100 startAngle:0 endAngle:kDegreesToRadians(135) clockwise:YES];
path.lineCapStyle = kCGLineCapRound; //線條拐角
path.lineJoinStyle = kCGLineJoinRound;//終點處理
path.lineWidth = 5.0;
UIColor *strokeColor = [UIColor redColor];
[strokeColor set];
[path stroke];
代碼解釋:startAngle、endAngle代表開始和結束的弧度,不是我們日常的角度,使用時候需要轉換成弧度。
效果圖如下:
畫二次貝塞爾曲線
controlPoint爲控制點
UIBezierPath *path = [UIBezierPath bezierPath];
//設置一個起始點
[path moveToPoint:CGPointMake(20, self.frame.size.height - 100)];
//添加二次曲線 controlPoint控制點
[path addQuadCurveToPoint:CGPointMake(self.frame.size.width - 20, self.frame.size.height - 100) controlPoint:CGPointMake(self.frame.size.width / 2, 0)];
path.lineCapStyle = kCGLineCapRound; //線條拐角
path.lineJoinStyle = kCGLineJoinRound; //終點處理
path.lineWidth = 5.0;
UIColor *strokeColor = [UIColor purpleColor];
[strokeColor set];
[path stroke];
效果圖如下:
畫三次貝塞曲線
三次貝塞爾曲線有兩個控制點
UIBezierPath *path = [UIBezierPath bezierPath];
//設置起始點
[path moveToPoint:CGPointMake(20, 150)];
//添加三次曲線 controlPoint1控制點1 controlPoint2控制點2
[path addCurveToPoint:CGPointMake(300, 150) controlPoint1:CGPointMake(160, 0) controlPoint2:CGPointMake(160, 250)];
path.lineCapStyle = kCGLineCapRound; //線條拐角
path.lineJoinStyle = kCGLineJoinRound; //終點處理
path.lineWidth = 5.0;
UIColor *strokeColor = [UIColor redColor];
[strokeColor set];
[path stroke];
效果圖如下:
CAShapeLayer結合UIBezierPath畫圖
CAShapeLayer *circleShapeLayer = [CAShapeLayer layer];
//設置frame
circleShapeLayer.frame = CGRectMake(0, 0, 200, 200);
circleShapeLayer.position = self.view.center;
//設置填充顏色
circleShapeLayer.fillColor = [UIColor clearColor].CGColor;
//設置線寬
circleShapeLayer.lineWidth = 2.0;
//設置線的顏色
circleShapeLayer.strokeColor = [UIColor redColor].CGColor;
CGRect frame = CGRectMake(0, 0, 200, 200);
//使用UIBezierPath創建路徑
UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect:frame];
//關聯CAShapeLayer與UIBezierPath
circleShapeLayer.path = circlePath.CGPath;
//將CAShaperLayer添加到某個層上顯示
[self.view.layer addSublayer:circleShapeLayer];
效果圖如下:
UIBezierPath動畫
-(void)startAnimation
{
AppDelegate *appDelegate = APP_DELEGATE;
if (!windowLayer) {
windowLayer = [CALayer layer];
windowLayer.bounds = [UIScreen mainScreen].bounds;
[appDelegate.window.layer addSublayer:windowLayer];
}
if (!layer)
{
layer = [CALayer layer];
layer.contents = (__bridge id)[UIImage imageNamed:@"icon_redDot.png"].CGImage;
layer.contentsGravity = kCAGravityResizeAspectFill;
layer.bounds = CGRectMake(100, 100, 20, 20);
[layer setCornerRadius:CGRectGetHeight([layer bounds]) / 2];
layer.masksToBounds = YES;
layer.position =CGPointMake(50, 150);
[appDelegate.window.layer addSublayer:layer];
}
layer.hidden = NO;
[self groupAnimation];
}
-(void)groupAnimation
{
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
animation.path = _path.CGPath;
animation.rotationMode = kCAAnimationRotateAuto;
//縮小
CABasicAnimation *narrowAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
narrowAnimation.beginTime = 0.5;
narrowAnimation.duration = 0.25f;
narrowAnimation.fromValue = [NSNumber numberWithFloat:2.0f];
narrowAnimation.toValue = [NSNumber numberWithFloat:0.5f];
narrowAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
CAAnimationGroup *groups = [CAAnimationGroup animation];
groups.animations = @[animation,narrowAnimation];
groups.duration = 0.5f;
groups.removedOnCompletion=NO;
groups.fillMode=kCAFillModeForwards;
groups.delegate = self;
[layer addAnimation:groups forKey:@"group"];
}
效果圖如下:
僅供交流學習,喜歡的隨手給個星星。Have fun!
參考文獻
http://blog.csdn.net/crayondeng/article/details/11093689
http://blog.csdn.net/yongyinmg/article/details/38844879