一.Quartz2D简介
Quartz2D是二维的绘图引擎(经包装的函数库,方便开发者使用。也就是说苹果帮我们封装了一套绘图的函数库),用Quartz2D写的同一份代码,既可以运行在iphone上又可以运行在mac上,可以跨平台开发,开发中比较常用的是截屏/裁剪/自定义UI控件,Quartz2D在iOS开发中的价值就是自定义UI控件.
二.绘图简介
1.绘图的步骤:
1.获取上下文
CG:表示这个类在CoreGraphics框架里 Ref:引用,目前学的上下文都跟UIGraphics有关,想获取图形上下文,首先敲UIGraphics。
2.创建路径(描述路径)
一般开发中用贝塞尔路径,里面封装了很多东西,可以帮我画一些基本的线段,矩形,圆等等
4.渲染上下文
首先获取图形上下文,然后描述路径,把路径添加到上下文,渲染到视图,图形上下文相当于一个内存缓存区,在内存里面操作是最快的,比直接在界面操作快多了
3.当这个View要显示的时候才会调用drawRect绘制图形,viewDidLoad后才会调用,因为那时候还没显示视图
4.注意:drawRect不能手动调用,因为图形上下文我们自己创建不了,只能由系统帮我们创建,并且传递给我们.需要我们手动调用 [self setNeedsDisplay](重绘,系统会先创建与view相关联的上下文,然后再调用drawRect)
三.Quartz2D绘图演练
1.绘制直线
最原始的绘图方式
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path,
NULL,
50,
50);
CGPathAddLineToPoint(path,
NULL,
200,
200);
CGContextAddPath(ctx, path);
CGContextStrokePath(ctx);
绘直线第二种方式
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextMoveToPoint(ctx,
50,
50);
CGContextAddLineToPoint(ctx,
200,
200);
CGContextStrokePath(ctx);
绘直线第三种方式
UIBezierPath
*path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(
50,
50)];
[path addLineToPoint:CGPointMake(
200,
200)];
[path
stroke];
2.绘制曲线
最原始的绘图方式
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextMoveToPoint(ctx,
50,
50);
CGContextAddQuadCurveToPoint(ctx,
150,
20,
250,
50);
CGContextStrokePath(ctx);
3.绘制图形
圆弧
CGPoint center = CGPointMake(
125,
125);
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:
100 startAngle:
0 endAngle:M_PI_2 clockwise:
YES];
[path addLineToPoint:center];
[path closePath];
[path stroke];
饼状图
- (
NSArray *)arrRandom
{
int totoal =
100;
NSMutableArray *arrM = [
NSMutableArray array];
int temp =
0;
for (
int i =
0; i < arc4random_uniform(
10) +
1; i++) {
temp = arc4random_uniform(totoal) +
1;
[arrM addObject:@(temp)];
if (temp == totoal) {
break;
}
totoal -= temp;
}
if (totoal) {
[arrM addObject:@(totoal)];
}
return arrM;
}
- (
void)drawRect:(
CGRect)rect {
NSArray *arr = [
self arrRandom];
CGFloat radius = rect
.size.width *
0.5;
CGPoint center = CGPointMake(radius, radius);
CGFloat startA =
0;
CGFloat angle =
0;
CGFloat endA =
0;
for (
int i =
0; i < arr
.count; i++) {
startA = endA;
angle = [arr[i] integerValue] /
100.0 * M_PI *
2;
endA = startA + angle;
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:
YES];
[path addLineToPoint:center];
[[
self colorRandom] set];
[path fill];
}
}
- (
void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[
self setNeedsDisplay];
}
- (
UIColor *)colorRandom
{
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];
}
柱状图
- (
void)drawRect:(
CGRect)rect {
NSArray *arr = [
self arrRandom];
CGFloat x =
0;
CGFloat y =
0;
CGFloat w =
0;
CGFloat h =
0;
for (
int i =
0 ; i < arr
.count; i++) {
w = rect
.size.width / (
2*arr
.count -
1);
x =
2 * w * i;
h = [arr[i] floatValue] /
100.0 *rect
.size.height;
y = rect
.size.height - h;
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(x, y, w, h)];
[[
self colorRandom] set];
[path fill];
}
}
- (
void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[
self setNeedsDisplay];
}
- (
NSArray *)arrRandom {
int total =
100;
NSMutableArray *arrM = [
NSMutableArray array];
int temp =
0;
for (
int i =
0 ; i < arc4random_uniform(
10) +
1; i++) {
temp = arc4random_uniform(total) +
1;
[arrM addObject:@(temp)];
if (temp == total) {
break;
}
total -= temp;
}
if (total) {
[arrM addObject:@(total)];
}
return arrM;
}
- (
UIColor *)colorRandom
{
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];
}
绘制文字
NSString *str = @
"asfdsfsdf";
NSMutableDictionary *textDict = [
NSMutableDictionary dictionary];
textDict[NSForegroundColorAttributeName] = [
UIColor redColor];
textDict[NSFontAttributeName] = [
UIFont systemFontOfSize:
30];
textDict[NSStrokeWidthAttributeName] = @
3;
textDict[NSStrokeColorAttributeName] = [
UIColor yellowColor];
NSShadow *shadow = [[NSShadow alloc] init];
shadow
.shadowColor = [
UIColor greenColor];
shadow
.shadowOffset = CGSizeMake(
4,
4);
shadow
.shadowBlurRadius =
3;
textDict[NSShadowAttributeName] = shadow;
[str drawAtPoint:CGPointZero withAttributes:textDict];
绘制图片
UIRectClip(CGRectMake(
0,
0,
50,
50));
UIImage *image = [
UIImage imageNamed:@
"001"];
[image drawAtPoint:CGPointZero];
4.绘图中的定时器
如果在绘图的时候需要用到定时器,通常使用CADisplayLink
CADisplayLink *link = [CADisplayLink displayLinkWithTarget:
self selector:
@selector(timeChange)];
[link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
- (
void)timeChange
{
[
self setNeedsDisplay];
}
5.矩阵操作(平移,缩放,旋转)
- (
void)drawRect:(
CGRect)rect {
CGContextRef ctx = UIGraphicsGetCurrentContext();
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-
100, -
50,
200,
100)];
[[
UIColor redColor] set];
CGContextTranslateCTM(ctx,
100,
50);
CGContextScaleCTM(ctx,
0.5,
0.5);
CGContextRotateCTM(ctx, M_PI_4);
CGContextAddPath(ctx, path
.CGPath);
[[
UIColor redColor] set];
CGContextFillPath(ctx);
}
四.Quartz2D应用
1.图片水印
UIImage *image = [
UIImage imageNamed:@
"小黄人"];
UIGraphicsBeginImageContextWithOptions(image
.size,
NO,
0);
UIBezierPath *path =[UIBezierPath bezierPathWithOvalInRect:CGRectMake(
0,
0,
300,
300)];
[[
UIColor redColor] set];
[path stroke];
[image drawAtPoint:CGPointZero];
NSString *str = @
"小码哥";
NSMutableDictionary *dict = [
NSMutableDictionary dictionary];
dict[NSForegroundColorAttributeName] = [
UIColor redColor];
dict[NSFontAttributeName] = [
UIFont systemFontOfSize:
20];
[str drawAtPoint:CGPointMake(
200,
528) withAttributes:dict];
UIImage *imageWater = UIGraphicsGetImageFromCurrentImageContext();
self.imageView.image = imageWater;
2.图片裁剪
+ (
UIImage *)imageWithClipImage:(
UIImage *)image borderWidth:(
CGFloat)borderWidth borderColor:(
UIColor *)color
{
CGFloat imageWH = image
.size.width;
CGFloat border = borderWidth;
CGFloat ovalWH = imageWH +
2 * border;
UIGraphicsBeginImageContextWithOptions(CGSizeMake(ovalWH, ovalWH),
NO,
0);
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(
0,
0, ovalWH, ovalWH)];
[color set];
[path fill];
UIBezierPath *clipPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(border, border, imageWH, imageWH)];
[clipPath addClip];
[image drawAtPoint:CGPointMake(border, border)];
UIImage *clipImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return clipImage;
}
3.图片截取
@property (
nonatomic,
assign)
CGPoint startP;
@property (
weak,
nonatomic)
UIImageView *imageV;
@property (
nonatomic,
weak)
UIView *clipView;
- (
UIView *)clipView{
if (_clipView ==
nil) {
UIView *view = [[
UIView alloc] init];
_clipView = view;
view
.backgroundColor = [
UIColor blackColor];
view
.alpha =
0.5;
[
self.view addSubview:view];
}
return _clipView;
}
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:
self action:
@selector(pan:)];
[
self.view addGestureRecognizer:pan];
- (
void)pan:(UIPanGestureRecognizer *)pan
{
CGPoint endA = CGPointZero;
if (pan
.state == UIGestureRecognizerStateBegan) {
_startP = [pan locationInView:
self.view];
}
else if(pan
.state == UIGestureRecognizerStateChanged){
endA = [pan locationInView:
self.view];
CGFloat w = endA
.x - _startP
.x;
CGFloat h = endA
.y - _startP
.y;
CGRect clipRect = CGRectMake(_startP
.x, _startP
.y, w, h);
self.clipView.frame = clipRect;
}
else if (pan
.state == UIGestureRecognizerStateEnded){
UIGraphicsBeginImageContextWithOptions(_imageV
.bounds.size,
NO,
0);
UIBezierPath *path = [UIBezierPath bezierPathWithRect:_clipView
.frame];
[path addClip];
CGContextRef ctx = UIGraphicsGetCurrentContext();
[_imageV
.layer renderInContext:ctx];
_imageV
.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[_clipView removeFromSuperview];
_clipView =
nil;
}
}
4.屏幕截屏
UIGraphicsBeginImageContextWithOptions(view
.bounds.size,
NO,
0);
CGContextRef ctx = UIGraphicsGetCurrentContext();
[view
.layer renderInContext:ctx];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
5.图片擦除
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:
self action:
@selector(pan:)];
[
self.view addGestureRecognizer:pan];
- (
void)pan:(UIPanGestureRecognizer *)pan
{
CGPoint curP = [pan locationInView:
self.view];
CGFloat wh =
100;
CGFloat x = curP
.x - wh *
0.5;
CGFloat y = curP
.y - wh *
0.5;
CGRect rect = CGRectMake(x, y, wh, wh);
UIGraphicsBeginImageContextWithOptions(
self.view .bounds.size,
NO,
0);
CGContextRef ctx=UIGraphicsGetCurrentContext();
[_imageView
.layer renderInContext:ctx];
CGContextClearRect(ctx, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
_imageView
.image = image;
UIGraphicsEndImageContext();
}