UIBezierPath基礎篇

由於項目中要加入一個類似於購物車的拋物線動畫的需求,開始研究了下貝塞爾曲線的相關內容,首先了解下UIBezierPath基礎。

UIBezierPath基礎

使用UIBezierPath類可以創建基於矢量的路徑,這個類在UIKit中。此類是Core Graphics框架關於path的一個封裝。使用此類可以定義簡單的形狀,如橢圓或者矩形,或者有多個直線和曲線段組成的形狀。

使用

UIBezierPath的使用

  1. 創建UIBezierPath對象;
  2. 調用moveToPoint設置初始路徑的地點;
  3. 添加line(線)或者curve(曲線)去定義一個或者多個subpaths(子路徑);
  4. 設置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"];
 }

效果圖如下:

這裏寫圖片描述

本文demo

僅供交流學習,喜歡的隨手給個星星。Have fun!

參考文獻
http://blog.csdn.net/crayondeng/article/details/11093689
http://blog.csdn.net/yongyinmg/article/details/38844879

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章