你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS開發---繪圖

iOS開發---繪圖

編輯:IOS開發綜合

繪圖操作

前言:在iOS開發中,系統已經給我們提供了功能強大的控件,可是很多並不能滿足我們的需求。這時候我們需要,自定義一些美觀的控件。所用的知識也就是下面的繪圖。

1.基本的繪圖知識

1.1圖形上下文

1.1圖形上下文(Graphics Context):是一個CGContextRef類型的數據

1.2圖形上下文的作用
保存繪圖信息、繪圖狀態
決定繪制的輸出目標(繪制到什麼地方去?)
(輸出目標可以是PDF文件、Bitmap或者顯示器的窗口上)
這裡寫圖片描述

1.2 - (void)drawRect:(CGRect)rect

作用:就是用來繪圖 什麼調用:當控件第一次顯示的時候 rect:當前控件的bounds

1.2 繪圖的步驟

1.獲得圖形上下文:

CGContextRef ctx = UIGraphicsGetCurrentContext();

2.拼接路徑

新建一個起點
void CGContextMoveToPoint(CGContextRef c, CGFloat x, CGFloat y)

添加新的線段到某個點
void CGContextAddLineToPoint(CGContextRef c, CGFloat x, CGFloat y)

添加一個矩形
void CGContextAddRect(CGContextRef c, CGRect rect)

添加一個橢圓
void CGContextAddEllipseInRect(CGContextRef context, CGRect rect)

添加一個圓弧

void CGContextAddArc(CGContextRef c, CGFloat x, CGFloat y,
CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise)

3.添加路徑到上下文

Mode參數決定繪制的模式
void CGContextDrawPath(CGContextRef c, CGPathDrawingMode mode)

繪制空心路徑
void CGContextStrokePath(CGContextRef c)

繪制實心路徑
void CGContextFillPath(CGContextRef c)

提示:一般以CGContextDraw、CGContextStroke、CGContextFill開頭的函數,都是用來繪制路徑的

4.渲染到View上面

1.3 基本的繪圖實例

1. 繪制線條

獲得圖形上下文: UIGraphicsGetCurrentContext() 拼接路徑:UIBezierPath 添加路徑到上下文 CGContextAddPath(ctx, path.CGPath) 渲染到View上面 CGContextStrokePath(ctx)
- (void)drawLine
{
    // 一個路徑對象,可以對應多跟線
    // 1.獲取跟當前view想關聯的上下文,系統自動幫我們創建的上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    // 設置上下文的狀態,應該放在渲染之前就可以
    // 創建對應顏色對象,調用set方法
    [[UIColor redColor] set];
    // 設置上下文的線寬
    CGContextSetLineWidth(ctx, 15);
    // 設置線段的連接樣式
    CGContextSetLineJoin(ctx, kCGLineJoinRound);
    // 設置線段的端點樣式
    CGContextSetLineCap(ctx, kCGLineCapRound);

    // 2.拼接路徑,UIBezierPath,封裝好了一套很好使用的路徑
    UIBezierPath *path = [UIBezierPath bezierPath];
    // 2.1 設置起點
    [path moveToPoint:CGPointMake(10, 125)];
    // 2.2 添加一根線到某個點
    [path addLineToPoint:CGPointMake(220, 125)];
    // 如果只使用一根路徑,默認下一根線的起點在上一根跟線終點
    [path addLineToPoint:CGPointMake(200, 150)];

    // 3.添加路徑到上下文
    CGContextAddPath(ctx, path.CGPath);
    // 4.渲染到view上面的圖層
    CGContextStrokePath(ctx);

}

2.繪制曲線

一般通過貝塞爾曲線來繪制圖形:UIBezierPath

-(void)drawLIneQuadCurve
{
    // 1.獲取上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    // 2.拼接路徑
    UIBezierPath *path = [UIBezierPath bezierPath];

    [path moveToPoint:CGPointMake(10, 125)];
    [path addQuadCurveToPoint:CGPointMake(240, 125) controlPoint:CGPointMake(125, 0)];

    // 3.路徑添加到上下文
    CGContextAddPath(ctx, path.CGPath);

    // 4.渲染上下文
    //以填充的方式渲染
    //CGContextFillPath(ctx);
    CGContextStrokePath(ctx);
}

3.繪制矩形

// 繪制矩形
- (void)drawRect
{
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(50, 50, 100, 100) cornerRadius:50];

    CGContextAddPath(ctx, path.CGPath);

    // 設置填充的顏色
    [[UIColor redColor] setFill];

    [[UIColor greenColor] setStroke];

    // 填充:必須封閉的路徑
    // 即描邊又填充
    // 如果以後只需要描邊,最好不要使用fill
    CGContextDrawPath(ctx, kCGPathFillStroke);
    //    CGContextFillPath(ctx);
    CGContextStrokePath(ctx);
}

4.繪制圓弧

- (void)drawRect:(CGRect)rect {
    // 畫圓弧
    // center:圓心
    // radius:半徑
    // clockwise:當前是 yes:順時針 no:逆時針
    CGPoint center = CGPointMake(125, 125);

    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(125, 125) radius:100 startAngle:0 endAngle:-M_PI_2  clockwise:NO];
    // 添加一根線到圓心
    [path addLineToPoint:center];

    // 關閉路徑:從路徑的終點到起點
    // [path closePath];

    // 填充,默認會關閉路徑,從路徑的終點到起點
    [path fill];
}

5.繪制文字

- (void)drawRect:(CGRect)rect
{
    //=========================繪制文字==========================
    NSString *name = @會長桂雛菊;
    // 描述文字的屬性,顏色,字體大小
    NSMutableDictionary *attr = [NSMutableDictionary dictionary];
    // 字體
    attr[NSFontAttributeName] = [UIFont systemFontOfSize:15];
    // 顏色
    attr[NSForegroundColorAttributeName] = [UIColor redColor];
    // 邊框顏色
    attr[NSStrokeColorAttributeName] = [UIColor redColor];
    // 邊框寬度
    attr[NSStrokeWidthAttributeName] = @1;

    // 陰影
    NSShadow *shadow = [[NSShadow alloc] init];
    shadow.shadowOffset = CGSizeMake(3, 3);
    shadow.shadowColor = [UIColor yellowColor];
    shadow.shadowBlurRadius = 3;

    attr[NSShadowAttributeName] = shadow;

    [name drawInRect:CGRectMake(90, 100, 100, 50) withAttributes:attr];
}

6.繪制餅狀圖

在初始化的時候時候,系統通過調用drawRect方法繪圖。但是如果我們要重繪,手動調用drawRect方法是無效的。不過系統為我們准備了重繪的方法:

重繪:setNeedsDisplay

- (void)drawRect:(CGRect)rect {
    // Drawing code
    NSArray *datas = @[@25,@25,@50];
    CGPoint center = CGPointMake(125, 125);
    CGFloat r = 100;
    CGFloat startA = 0;
    CGFloat angle = 0;
    CGFloat endA = 0;
    for (NSNumber *number in datas) {
        // 遍歷一個數據,繪制一根扇形
        startA = endA;
        angle = number.intValue / 100.0 * M_PI * 2;
        endA = startA + angle;
        // 描述圓弧
        UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:r startAngle:startA endAngle:endA clockwise:YES];

        [path addLineToPoint:center];

        [[self randomColor] set];

        [path fill];
    }
}
//當點擊View的時候,重繪
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self setNeedsDisplay];

}
//生成隨機的顏色
- (UIColor *)randomColor
{
    CGFloat r = arc4random_uniform(256) / 255.0;
    CGFloat g = arc4random_uniform(256) / 255.0;
    CGFloat b = arc4random_uniform(256) / 255.0;
    return [UIColor colorWithRed:r green:g blue:b alpha:1];
}

7.上下文棧

將當前的上下文copy一份,保存到棧頂(那個棧叫做”圖形上下文棧”):
void CGContextSaveGState(CGContextRef c)

將棧頂的上下文出棧,替換掉當前的上下文:
void CGContextRestoreGState(CGContextRef c)

- (void)drawRect:(CGRect)rect {
    // Drawing code

    // 1.獲取上下文
    CGContextRef ctx =  UIGraphicsGetCurrentContext();
    // 2.拼接路徑
    UIBezierPath *path = [UIBezierPath bezierPath];
    // 橫
    [path moveToPoint:CGPointMake(10, 150)];
    [path addLineToPoint:CGPointMake(290, 150)];
    // 3.把路徑添加到上下文
    CGContextAddPath(ctx, path.CGPath);

    //================================================
    // 保存上下文狀態
    CGContextSaveGState(ctx);
    //================================================
    // 設置上下文的狀態
    CGContextSetLineWidth(ctx, 10);
    [[UIColor redColor] set];

    // 4.渲染上下文,查看上下文的狀態,根據狀態去渲染
    CGContextStrokePath(ctx);
    // 豎
    path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(150, 10)];
    [path addLineToPoint:CGPointMake(150, 290)];

    // 3.把路徑添加到上下文
    CGContextAddPath(ctx, path.CGPath);

    // ==============================================
    // 從上下文狀態棧裡面取出保存的狀態,替換掉當前的狀態
    CGContextRestoreGState(ctx);
    // =============================================

    // 4.渲染上下文,查看上下文的狀態,根據狀態去渲染
    CGContextStrokePath(ctx);

}

8.上下文的平移,旋轉,縮放

利用矩陣操作,能讓繪制到上下文中的所有路徑一起發生變化
縮放

void CGContextScaleCTM(CGContextRef c, CGFloat sx, CGFloat sy)

旋轉
void CGContextRotateCTM(CGContextRef c, CGFloat angle)

平移
void CGContextTranslateCTM(CGContextRef c, CGFloat tx, CGFloat ty)

- (void)drawRect:(CGRect)rect {
    // 獲取上下文
   CGContextRef ctx =  UIGraphicsGetCurrentContext();

    // 拼接路徑
    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-100, -50, 200, 100)];
    // 矩陣操作:必須要在添加路徑之前進行形變
    // 平移上下文
    CGContextTranslateCTM(ctx, 100, 100);
    // 旋轉
    CGContextRotateCTM(ctx, M_PI_4);
    // 縮放
    CGContextScaleCTM(ctx, 0.5, 0.5);

    // 添加路徑到上下文
    CGContextAddPath(ctx, path.CGPath);

    // 渲染上下文
    CGContextFillPath(ctx);
}

9.圖片加水印

1.開啟一個基於位圖的圖形上下文
void UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale)

size:上下文尺寸 opaque:不透明 Yes 不透明 透明 NO scale:是否縮放上下文,0表示不要縮放

2.從上下文中取得圖片(UIImage):

UIImage* UIGraphicsGetImageFromCurrentImageContext()

3.結束基於位圖的圖形上下文:

void UIGraphicsEndImageContext()

- (void)viewDidLoad {開啟一個基於位圖的圖形上下文
void     UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale)

    [super viewDidLoad];

    UIImage *image = [UIImage imageNamed:@hina];
    // 創建位圖上下文
    UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);

    [image drawAtPoint:CGPointZero];

    // 文字
    NSString *str = @會長桂雛菊;
    [str drawAtPoint:CGPointMake(0, 0) withAttributes:nil];
    // 根據上下文的內容生成一張圖片
    image = UIGraphicsGetImageFromCurrentImageContext();
    // 關閉上下文
    UIGraphicsEndImageContext();

    // 用來網絡中傳輸圖片
    NSData *data = UIImagePNGRepresentation(image);
    [data writeToFile:@/Users/apple/Desktop/image.png atomically:YES];
}

10.圖片裁剪

1.將當前上下所繪制的路徑裁剪出來(超出這個裁剪區域的都不能顯示):

void CGContextClip(CGContextRef c)

思路分析
先畫一個大圓,在設置裁剪區域,把圖片畫上去,超出裁剪區域的自動裁剪掉。
* 加載舊圖片,根據舊圖片,獲取上下文尺寸。
* 確定圓環寬度 borderW
* 上下文的尺寸 = 新圖片的尺寸
* 確定新的上下文尺寸: newImageW : oldImageW + 2 * borderW newImageH : oldImageH + 2 * borderW,
* 繪制大圓:
1.獲取上下文 2.添加路徑到上下文 3.設置大圓的顏色 = 圓環的顏色 4.渲染
* 設置裁剪區域,和圖片尺寸一樣大,只不過,x,y不一樣,x=borderW,y=borderW.
* 繪制舊圖片
* 獲取新圖片
* 關閉上下文
* 抽分類,3個參數,圖片名稱,圓環寬度,圓環顏色

+ (UIImage*)imageCircleWithImage:(UIImage *)image borderWidth:(CGFloat)borderWidth borderColor:(UIColor *)borderColor
{
    // 設置圓環寬度
    CGFloat boardW = borderWidth;
    CGFloat imageW =  image.size.width + 2 * boardW;
    CGFloat imageH = image.size.height + 2 *boardW;

    // 只有正方形才能正切圓,選擇一個最短的尺寸,正切。
    CGFloat circleW = imageW > imageH ? imageH : imageW;
    CGRect rect = CGRectMake(0, 0, circleW, circleW);

    // 2.開啟圖像上下文
    UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0.0);
    // 3。獲取當前上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    // 4.畫外圓
    UIBezierPath *path  = [UIBezierPath bezierPathWithOvalInRect:rect];
    CGContextAddPath(ctx, path.CGPath);

    [borderColor set];

    CGContextFillPath(ctx);

    // 設置頭像尺寸
    rect = CGRectMake(boardW, boardW, image.size.width , image.size.height);

    // 5.創建裁剪路徑
    UIBezierPath *clipPath = [UIBezierPath bezierPathWithOvalInRect:rect];

    // 6.裁剪路徑
    // 根據這個路徑進行裁剪,超出路徑以外的部分就不會顯示了
    [clipPath addClip];

    // 7.畫頭像
    [image drawInRect:rect];

    // 不能直接在這返回,上下文沒有關閉,會消耗內存.
    // 8.獲取新圖片
    image = UIGraphicsGetImageFromCurrentImageContext();

    // 9.關閉上下文
    UIGraphicsEndImageContext();

    return image;

}

11.截取屏幕

View之所以能顯示東西,完全是因為它內部的layer。View內部有個layer(圖層)屬性,drawRect:方法中取得的是一個Layer Graphics Context,因此,繪制的東西其實是繪制到view的layer上去了

- (void)renderInContext:(CGContextRef)ctx;

//截取屏幕
+ (UIImage*)imageWithCaptureView:(UIView*)captureView;
{
    // 1.開啟上下文
    UIGraphicsBeginImageContextWithOptions(captureView.bounds.size, NO, 0.0);
    // 2.獲取當前上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    // 3.把控制器圖層渲染到上下文
    [captureView.layer renderInContext:ctx];
    // 4.取出新圖片
    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return newImage;
}

 

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved