iOS上怎么繪制如下的小黃人呢?
在iOS系統(tǒng)中毡泻,UIView是最基礎的顯示控件胜茧,UILabel、UIButton都是它的子類仇味。如果需要自定義新的UI控件樣式呻顽,它也必須繼承自UIView。
這里我們先自定義一個MinionsView
試試丹墨,它的m文件如下:
#import "MinionsView.h"
@implementation MinionsView
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/
@end
你會發(fā)現其中生成了一段被注釋方法 drawRect 廊遍,而這正是自定義View最核心的方法。一般情況下它只在視圖顯示在屏幕上的時候被系統(tǒng)調用一次贩挣。
接下來的問題是怎么繪制出我們想要的View樣式呢喉前?
iOS給我們提供一個二維圖形繪制引擎Quartz 2D。
Quartz 2D是一個二維圖形繪制引擎揽惹,支持iOS環(huán)境和Mac OS X環(huán)境被饿。我們可以使用Quartz 2D API來實現許多功能,如基本路徑的繪制搪搏、透明度狭握、描影、繪制陰影疯溺、透明層论颅、顏色管理、反鋸齒囱嫩、PDF文檔生成和PDF元數據訪問恃疯。在需要的時候,Quartz 2D還可以借助圖形硬件的功能墨闲。
在Mac OS X中今妄,Quartz 2D可以與其它圖形圖像技術混合使用,如Core Image鸳碧、Core Video盾鳞、OpenGL、QuickTime。例如,通過使用 QuickTime的GraphicsImportCreateCGImage函數跑筝,可以用 Quartz從一個 QuickTime圖形導入器中創(chuàng)建一個圖像。
Quartz 2D是一個純C的庫推励,接口完全面向過程鹤耍,挺簡單的。
一验辞、繪制流程
基本流程3步:
- 獲得圖形上下文:
CGContextRef context = UIGraphicsGetCurrentContext();
- 繪制圖形稿黄。
- 將繪制的圖形顯示在UIView上。
CGContextFillPath(context);
CGContextStrokePath(context);
這里面上下文有點像畫筆跌造,存放著畫筆的寬度
抛猖、空心顏色
、實心顏色
鼻听,為了避免頻繁設置屬性,可以保存到棧里面联四。
// 保存CG上下文撑碴,放入棧中
CGContextSaveGState(context);
// 將CG上下文出棧,替換當前的上下文
CGContextRestoreGState(context);
二朝墩、繪制基礎元素
- 繪制線條
#pragma mark - 繪制線條
void drawline(){
#pragma mark - 繪制斜線
// 1:獲得圖形上下文
CGContextRef context = UIGraphicsGetCurrentContext();
// 保存CG上下文醉拓,放入棧中
CGContextSaveGState(context);
// 2:繪制圖形
// 設置一下線段的寬度
CGContextSetLineWidth(context, 10);
// 設置顏色
CGContextSetRGBStrokeColor(context, 1, 0, 0, 1);
// 設置起點
CGContextMoveToPoint(context, 10, 10);
// 設置線條終點
CGContextAddLineToPoint(context, 100, 100);
// 3:將繪制的圖形顯示在UIView上
CGContextStrokePath(context); // 以空心的方式畫出
#pragma mark - 繪制兩條線
// 將CG上下文出棧,替換當前的上下文
CGContextRestoreGState(context);
[[UIColor blueColor] set];
// CGContextSetLineWidth(context, 10);
// 設置線條頭尾部的樣式
// kCGLineCapButt: 該屬性值指定不繪制端點收苏, 線條結尾處直接結束亿卤。這是默認值。
// kCGLineCapRound: 該屬性值指定繪制圓形端點鹿霸, 線條結尾處繪制一個直徑為線條寬度的半圓
// kCGLineCapSquare: 該屬性值指定繪制方形端點排吴。
CGContextSetLineCap(context, kCGLineCapRound);
// 設置線段轉折點的樣式
CGContextSetLineJoin(context, kCGLineJoinRound);
// 畫線
CGContextMoveToPoint(context, 100, 120);
CGContextAddLineToPoint(context, 150, 120);
CGContextAddLineToPoint(context, 150, 180);
CGContextAddLineToPoint(context, 200, 180);
CGContextStrokePath(context);
}
- 繪制四邊形
#pragma mark - 繪制實心四邊形
void drawR(){
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextAddRect(context, CGRectMake(10, 10, 120, 180));
[[UIColor purpleColor] setFill];
CGContextFillPath(context);
}
- 繪制三角形
#pragma mark - 繪制空心三角形
void drawTriangle(){
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextMoveToPoint(context, 0, 0);
CGContextAddLineToPoint(context, 100, 100);
CGContextAddLineToPoint(context, 150, 100);
//關閉路徑(連接起點和最后一個點)
CGContextClosePath(context);
[[UIColor redColor] set];
CGContextStrokePath(context);
}
- 繪制圓
#pragma mark - 繪制圓
void drawCircle(){
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextAddEllipseInRect(context, CGRectMake(50, 50, 100, 100));
CGContextSetLineWidth(context, 10);
CGContextStrokePath(context);
}
- 繪制圓弧
#pragma mark - 繪制圓弧
// 角度轉弧度
CGFloat arc(CGFloat angle){
return angle * (M_PI / 180);
}
void drawArc(){
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextAddArc(context, 100, 100, 50, arc(90), arc(200), 1);
// CGContextStrokePath(context);
CGContextFillPath(context);
}
- 繪制文字
#pragma mark - 繪制文字
void drawText(){
NSString *str = @"我是文字";
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
attributes[NSFontAttributeName] = [UIFont systemFontOfSize:20]; // 設置文字大小
attributes[NSForegroundColorAttributeName] = [UIColor purpleColor]; // 設置文字顏色
[str drawInRect:CGRectMake(100, 100, 100, 30) withAttributes:attributes];
}
- 繪制圖片
#pragma mark - 繪制圖片
void drawPicture(){
UIImage *image = [UIImage imageNamed:@"1.png"];
// [image drawAtPoint:CGPointMake(50, 50)];
// [image drawInRect:CGRectMake(0, 0, 100, 100)];
[image drawAsPatternInRect:CGRectMake(0, 0, 300, 300)]; //平鋪
NSString *str = @"我是圖片";
[str drawInRect:CGRectMake(30, 30, 100, 30) withAttributes:nil];
}
- 繪制貝塞爾曲線
#pragma mark - 貝塞爾曲線
void drawBezier(){
CGContextRef context = UIGraphicsGetCurrentContext();
// 設置起點
CGContextMoveToPoint(context, 10, 10);
// 設置2個控制點
CGContextAddCurveToPoint(context, 120, 100, 180, 50, 190, 190);
// 設置1個控制點
// CGContextAddQuadCurveToPoint(context, 150, 200, 200, 100);
CGContextStrokePath(context);
}
三、挑戰(zhàn)大BOSS:繪制小黃人
//
// MinionsView.m
// PandaiOSDemo
//
// Created by shitianci on 16/7/7.
// Copyright ? 2016年 Panda. All rights reserved.
//
#import "MinionsView.h"
#define JYFRadius 70
#define JYFTopY 100
#define JYFColor(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1.0]
@implementation MinionsView
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
CGContextRef context = UIGraphicsGetCurrentContext();
drawBody(context, rect);
drawMouse(context, rect);
drawEyes(context, rect);
}
#pragma mark - 繪制身體
void drawBody(CGContextRef context,CGRect rect){
// 上半圓
CGFloat topX = rect.size.width * 0.5;
CGFloat topY = JYFTopY;
CGFloat topRadius = JYFRadius;
CGContextAddArc(context, topX, topY, topRadius, 0, M_PI, 1);
// 向下延伸的直線
CGFloat starPoint = topX - topRadius;
CGFloat leftHeight = JYFTopY;
CGFloat endPoint = topY + leftHeight;
CGContextAddLineToPoint(context, starPoint, endPoint);
// 下半圓
CGFloat bottomX = topX;
CGFloat bottomY = endPoint;
CGFloat bottomRadius = topRadius;
CGContextAddArc(context, bottomX, bottomY, bottomRadius, M_PI, 0, 1);
// 合并路徑
CGContextClosePath(context);
// 設置顏色
[JYFColor(252, 218, 0) set];
CGContextFillPath(context);
}
#pragma mark - 繪制嘴巴
void drawMouse(CGContextRef context,CGRect rect){
// 設置一個控制點
CGFloat controlX = rect.size.width * 0.5;
CGFloat controlY = rect.size.height * 0.4;
// 設置當前點
CGFloat marginX = 20;
CGFloat marginY = 10;
CGFloat currentX = controlX - marginX;
CGFloat currentY = controlY - marginY;
CGContextMoveToPoint(context, currentX, currentY);
// 設置結束點
CGFloat endX = controlX + marginX;
CGFloat endY = currentY;
// 繪制貝塞爾曲線
CGContextAddQuadCurveToPoint(context, controlX, controlY, endX, endY);
// 設置顏色
[[UIColor blackColor] set];
// 顯示
CGContextStrokePath(context);
}
#pragma mark - 繪制眼睛
void drawEyes(CGContextRef context,CGRect rect){
// 黑色綁帶
// 起點
CGFloat startPointX = rect.size.width * 0.5 - JYFRadius;
CGFloat startPointY = JYFTopY;
CGContextMoveToPoint(context, startPointX, startPointY);
// 結束點
CGFloat endX = startPointX + JYFRadius * 2;
CGFloat endY = startPointY;
CGContextAddLineToPoint(context, endX, endY);
CGContextSetLineWidth(context, 15);
[[UIColor blackColor] set];
CGContextStrokePath(context);
// 灰色鏡框
[JYFColor(61, 62, 66) set];
CGFloat kuangRadius = JYFRadius * 0.4;
CGFloat kuangX = rect.size.width * 0.5 - kuangRadius;
CGFloat kuangY = startPointY;
CGContextAddArc(context, kuangX + 25, kuangY, kuangRadius, 0, M_PI * 2, 0);
CGContextFillPath(context);
// 白色鏡框
[[UIColor whiteColor] set];
CGFloat whiteRadius = kuangRadius * 0.7;
CGFloat whiteX = kuangX;
CGFloat whiteY = kuangY;
CGContextAddArc(context, whiteX + 25, whiteY, whiteRadius, 0, M_PI * 2, 0);
CGContextFillPath(context);
// 黑色眼珠
[[UIColor blackColor] set];
CGFloat eyeRadius = whiteRadius * 0.5;
CGFloat eyeX = whiteX;
CGFloat eyeY = whiteY;
CGContextAddArc(context, eyeX + 25, eyeY, eyeRadius, 0, M_PI * 2, 1);
CGContextFillPath(context);
}
@end
參考資料
Panda
2016-07-07