配色: 字号:
iOS 开发 Quartz 2D+ UIBezierPath绘图大全详解
2016-12-05 | 阅:  转:  |  分享 
  
iOS开发Quartz2D+UIBezierPath绘图大全详解

Quartz2D使用大全结构图



UIKItUIBezierPathCoreGraphicsOpenGLESQuartz2D的区别和联系

UIKIt:UIKit中的控件都是基于CoreGraphics实现的

UIBezierPath:UIBezierPath属于UIKit,它是苹果对复杂的CoreGraphics进行的封装,方便我们用OC语言进行简单的绘图

CoreGraphics:是一套基于C语言的API,支持向量图形,线、形状、图案、路径、剃度、位图图像和pdf内容的绘制。

OpenGLES:OpenGL是由SGI公司开发的一套3D图形软件接口标准,它只是一个标准,具体实现由机械制造商来完成,所以不同的机器他的效果可能是完全不一样的。OpenGL-ES版本,主要是应对嵌入式环境和应用的要求,应该说在高效完成2D/3D界面的同时,达到了降低功耗的效果。

Quartz2D:quartz是一个通用的术语,用于描述在IOS整个媒体层用到的多种技术包括图形、动画、音频、适配。Quart2D是一组二位绘图和渲染API,CoreGraphic会使用到这组API

CoreGraphics框架

绘图我们要用到CoreGraphics框架,CoreGraphicsFramework是一套基于C的API框架,使用了Quartz作为绘图引擎。该框架可以用于基于路径的绘图、变换、颜色管理、脱屏渲染,模板、渐变、遮蔽、图像数据管理、图像的创建、遮罩以及PDF文档的创建、显示和分析。

CoreGraphicsAPI所有的操作都在一个上下文中进行。所以在绘图之前需要获取该上下文并传入执行渲染的函数中。介绍两种最为常用的获取方法。

第一种方法就是创建一个图片类型的上下文。调用UIGraphicsBeginImageContextWithOptions函数就可获得用来处理图片的图形上下文。利用该上下文,你就可以在其上进行绘图,并生成图片。调用UIGraphicsGetImageFromCurrentImageContext函数可从当前上下文中获取一个UIImage对象。记住在你所有的绘图操作后别忘了调用UIGraphicsEndImageContext函数关闭图形上下文。

第二种方法是利用cocoa为你生成的图形上下文。当你子类化了一个UIView并实现了自己的drawRect:方法后,一旦drawRect:方法被调用,Cocoa就会为你创建一个图形上下文,此时你对图形上下文的所有绘图操作都会显示在UIView上。

什么是Quartz2D绘图引擎

Quartz2D是,iOS中Quartz2D画出来的。

Quartz2D是纯C语言的

Quartz2D的API来自于CoreGraphics框架

数据类型和函数基本都是CG作为前缀?

CGContextRef

CGPathRef

CGContextStrokePath(ctx)

Quartz2D能完成的工作

绘制图形:线条\三角形\矩形\圆\弧形

绘制文字

绘制\生成图片(图像)

读取\生成PDF

截图\裁剪图片

自定义UI控件

Quartz2D绘图有以下两种方式



注意:UIBezierPath对象可以独立使用,无需手动获取“图形上下文”对象,此处为了更好的理解“图形上下文对象”所以暂时还是采用手动获取“图形上下文”对象的方式来绘图。

drawRect:方法的使用

View内部有个layer(图层)属性,drawRect:方法中取得的是一个LayerGraphicsContext,因此,绘制的东西其实是绘制到view的layer上去了

iOS的绘图操作是在UIView类的drawRect方法中完成的,重写drawRect方法,在这里进行绘图操作,程序会自动调用此方法进行绘图。

重绘操作仍然在drawRect方法中完成,苹果要求我们调用UIView类中的setNeedsDisplay方法,则程序会自动调用drawRect方法进行重绘。(调用setNeedsDisplay会自动调用drawRect)。

在UIView中,重写drawRect:(CGRect)aRect方法,可以自己定义想要画的图案.且此方法一般情况下只会画一次.也就是说这个drawRect方法一般情况下只会被掉用一次.当某些情况下想要手动重画这个View,只需要掉用[selfsetNeedsDisplay]方法即可.

rect指的就是当前view的bounds,即当前视图的所有范围。

drawRect:方法是系统帮我们调用的,不能手动去调用这个方法。原因是手动去调用drawRect方法的时候无法保证系统已经帮我们创建好了”图形上下文”,所以这样就无法保证在drawRect:方法中获取”图形上下文”对象,也就无法进行绘图了。

当这个view第一次显示的时候会调用一次drawRect方法;?当这个view执行重绘操作的时候会重新调用drawRect方法;?通过调用[selfsetNeedsDisplay]【重绘整个view】或[selfsetNeedsDisplayInRect:]【重绘指定区域】的方式让view执行drawRect方法进行重绘。

图形上下文CGContextRef

图形上下文的本质:是一个Quartz2D的绘图环境!



几种不同的渲染方式

?

通过C语言的API绘制基本图形

#pragmamark-通过C语言的API绘制基本图形

-(void)drawRect:(CGRect)rect{



//1.获取上下文

CGContextRefcxtRef=UIGraphicsGetCurrentContext();

//2.设置起点

CGContextMoveToPoint(cxtRef,50,50);

//3.添加线

CGContextAddLineToPoint(cxtRef,150,150);

//3.2继续加线段

CGContextAddLineToPoint(cxtRef,250,50);



//3.3向下的线

//注意:如果想要新开线,需要重新设置起点!

CGContextMoveToPoint(cxtRef,150,150);

CGContextAddLineToPoint(cxtRef,150,250);



//4.渲染

//kCGPathFill将线段包含的部分渲染成黑色!

//kCGPathStroke只负责绘制线条!

CGContextDrawPath(cxtRef,kCGPathStroke);

}

UIBezierPath进行直线图形绘制

#pragmamark-通过UIBezierPath进行图形绘制

//不用写关于图形上下文的代码,已经封装了,但是本质,还是需要获取到view相关的图形上下文,进行绘制!

-(void)drawRect:(CGRect)rect{



//1.获取图形上下文

//CGContextRefcxtRef=UIGraphicsGetCurrentContext();



//2.创建路径

UIBezierPathpath=[UIBezierPathbezierPath];

//3.1设置起点

[pathmoveToPoint:CGPointMake(50,50)];

//3.2添加线

[pathaddLineToPoint:CGPointMake(150,150)];

[pathaddLineToPoint:CGPointMake(250,50)];



//4.渲染--不写图形上下文的代码时,直接使用此方法渲染绘制

[pathstroke];



//4.将路径对象添加到图形上下文

//CGContextAddPath(cxtRef,path.CGPath);

//5.渲染

//CGContextDrawPath(cxtRef,kCGPathStroke);

}

UIBezierPath绘制矩形

//MARK:-1.矩形

-(void)drawRect:(CGRect)rect{

//1.获取图形上下文

//CGContextRefcxtRef=UIGraphicsGetCurrentContext();



//2.创建矩形的路径

UIBezierPathpath=[UIBezierPathbezierPathWithRect:CGRectMake(50,50,200,80)];

//3.渲染

[pathstroke];



//3.添加路径到图形上下文

//CGContextAddPath(cxtRef,path.CGPath);

//4.渲染

//CGContextDrawPath(cxtRef,kCGPathStroke);

}

UIBezierPath绘制圆角矩形

//MARK:-2.圆角矩形

-(void)drawRect:(CGRect)rect{

////1.获取图形上下文

//CGContextRefcxtRef=UIGraphicsGetCurrentContext();



//2.创建路径

CGFloatradius=20;

UIBezierPathpath=[UIBezierPathbezierPathWithRoundedRect:CGRectMake(50,50,200,80)cornerRadius:radius];

//3.渲染

[pathstroke];



////3.添加路径

//CGContextAddPath(cxtRef,path.CGPath);

////4.渲染

//CGContextDrawPath(cxtRef,kCGPathStroke);

}

UIBezierPath绘制椭圆

////1.获取图形上下文

//CGContextRefcxtRef=UIGraphicsGetCurrentContext();



//2.创建椭圆的路径

UIBezierPathpath=[UIBezierPathbezierPathWithOvalInRect:CGRectMake(50,50,200,80)];

//3.渲染

[pathstroke];



////3.添加

//CGContextAddPath(cxtRef,path.CGPath);

////4.渲染

//CGContextDrawPath(cxtRef,kCGPathStroke);

UIBezierPath绘制弧形

-(void)drawRect:(CGRect)rect{



//MARK:-4.弧形

////1.获取上下文

//CGContextRefcxtRef=UIGraphicsGetCurrentContext();



//2.圆弧路径

/

center圆心

radius半径

startAngle起始角度

endAngle结束角度

clockwise是否为顺时针!

/

//圆心

CGPointcenter=CGPointMake(150,150);

//半径

CGFloatradius=100;

//起始角度

CGFloatstartA=0;

//结束角度

CGFloatendA=M_PI_2;



//是否为顺时针

BOOLclockwise=NO;



UIBezierPathpath=[UIBezierPathbezierPathWithArcCenter:centerradius:radiusstartAngle:startAendAngle:endAclockwise:clockwise];



//3.渲染

[pathstroke];



////3.添加路径

//CGContextAddPath(cxtRef,path.CGPath);

////4.渲染

//CGContextDrawPath(cxtRef,kCGPathStroke);

}

UIBezierPath绘制圆形

//2.圆路径

/

center圆心

radius半径

startAngle起始角度

endAngle结束角度

clockwise是否为顺时针!

/

//圆心

CGPointcenter=CGPointMake(150,150);

//半径

CGFloatradius=100;

//起始角度

CGFloatstartA=0;

//结束角度

CGFloatendA=M_PI2;



//是否为顺时针

BOOLclockwise=NO;



UIBezierPathpath=[UIBezierPathbezierPathWithArcCenter:centerradius:radiusstartAngle:startAendAngle:endAclockwise:clockwise];



//渲染

[pathstroke];

UIBezierPath绘制扇形

//2.圆弧路径

/

center圆心

radius半径

startAngle起始角度

endAngle结束角度

clockwise是否为顺时针!

/

//圆心

CGPointcenter=CGPointMake(150,150);

//半径

CGFloatradius=100;

//起始角度

CGFloatstartA=0;

//结束角度

CGFloatendA=M_PI_4;



//是否为顺时针

BOOLclockwise=YES;



UIBezierPathpath=[UIBezierPathbezierPathWithArcCenter:centerradius:radiusstartAngle:startAendAngle:endAclockwise:clockwise];



//2.2向圆心添加线

[pathaddLineToPoint:center];



//渲染

[pathfill];

绘图状态信息设置

1>设置线宽CGContextSetLineWidth?2>设置线头样式CGContextSetLineCap?3>设置线段接头样式CGContextSetLineJoin?4>颜色的设置[[UIColorredColor]set]

-(void)drawRect:(CGRect)rect{



////1.获取图形上下文

CGContextRefcxtRef=UIGraphicsGetCurrentContext();



//2.创建矩形的路径

UIBezierPathpath=[UIBezierPathbezierPath];



[pathmoveToPoint:CGPointMake(50,50)];

//第一根线

[pathaddLineToPoint:CGPointMake(150,150)];

//第二根线

[pathaddLineToPoint:CGPointMake(250,50)];



//3.添加路径到图形上下文

CGContextAddPath(cxtRef,path.CGPath);



//3.1设置线宽!

CGContextSetLineWidth(cxtRef,20);

//3.2设置线头样式

/

kCGLineCapButt,比较难看的!

kCGLineCapRound,圆角

kCGLineCapSquare平角

/

CGContextSetLineCap(cxtRef,kCGLineCapButt);



//3.3设置接头的样式

/

kCGLineJoinMiter,尖头

kCGLineJoinRound,圆角

kCGLineJoinBevel多余的部分感觉被切了!

/

CGContextSetLineJoin(cxtRef,kCGLineJoinMiter);



//3.4颜色的设置

[[UIColorredColor]setStroke];

[[UIColoryellowColor]setFill];



//4.渲染

CGContextDrawPath(cxtRef,kCGPathFillStroke);

}



两种填充原则

-(void)drawRect:(CGRect)rect{



#pragmamark-非零绕数填充规则

[selfnonzeroWindingNumberRule];



#pragmamark-奇偶填充规则

[selfevenOddRule];

}



#pragmamark-非零绕数填充规则

/

非零绕数填充规则:

在图形上下文中的任何一个点

被顺时针覆盖标记为1

被逆时针覆盖标记为-1

当标记为0的时候不填充,其他则填充

这个规则与方向有关,与次数无关

/

-(void)nonzeroWindingNumberRule{



//1.获取图形上下文

CGContextRefcxtRef=UIGraphicsGetCurrentContext();



//2.绘制顺时针的圆形

UIBezierPatharcY=[UIBezierPathbezierPathWithArcCenter:CGPointMake(150,150)radius:100startAngle:0endAngle:M_PI2clockwise:YES];



//3.绘制逆时针的圆形

UIBezierPatharcN=[UIBezierPathbezierPathWithArcCenter:CGPointMake(150,150)radius:75startAngle:0endAwww.shanxiwang.netngle:M_PI2clockwise:NO];



//验证与次数无关

UIBezierPatharc3=[UIBezierPathbezierPathWithArcCenter:CGPointMake(150,230)radius:50startAngle:0endAngle:M_PI2clockwise:NO];



//4.添加路径对象

CGContextAddPath(cxtRef,arcY.CGPath);

CGContextAddPath(cxtRef,arcN.CGPath);

CGContextAddPath(cxtRef,arc3.CGPath);



[[UIColoryellowColor]setFill];



//5.渲染

CGContextDrawPath(cxtRef,kCGPathFill);



}



#pragmamark-奇偶填充规则

//even:偶数odd:偶数

/

奇偶填充规则解释:

在图形上下文中的任何一个点

如果它被路径对象覆盖了奇数次,在进行渲染操作的时候这个点就会被渲染

如果它被路径对象覆盖了偶数次,在进行渲染操作的时候这个点就不会被渲染

/

-(void)evenOddRule{



//获取图形上下文

CGContextRefcxtRef=UIGraphicsGetCurrentContext();



//绘制水平方向矩形

UIBezierPathrectH=[UIBezierPathbezierPathWithRect:CGRectMake(50,100,200,100)];



//绘制圆形

UIBezierPatharcPath=[UIBezierPathbezierPathWithArcCenter:CGPointMake(150,150)radius:75startAngle:0endAngle:M_PI2clockwise:YES];



//绘制竖直方向的矩形

UIBezierPathrectV=[UIBezierPathbezierPathWithRect:CGRectMake(180,25,50,250)];



//将路径对象添加到图形上下文中

CGContextAddPath(cxtRef,rectH.CGPath);

CGContextAddPath(cxtRef,arcPath.CGPath);

CGContextAddPath(cxtRef,rectV.CGPath);



[[UIColororangeColor]setFill];



//同时显示stroke和fill的颜色

CGContextDrawPath(cxtRef,kCGPathEOFill);

}





模拟下载进度条

思路:?在控制器中将slider的值传递给自定义view?在自定义View中,根据传递过来的值绘制弧。?创建一个与自定义view一样大小的label来显示下载进度

#import



@interfaceDownloadView:UIView

/

接收滑块的值

/

@property(nonatomic,assign)floatsliderValue;

@end

#import"DownloadView.h"



@interfaceDownloadView()



//需要先写,再拖线!

/

显示百分比的label

/

@property(nonatomic,weak)IBOutletUILabelvalueLbl;



@end



@implementationDownloadView



#pragmamark-重写set方法,执行重绘操作

-(void)setSliderValue:(float)sliderValue{

_sliderValue=sliderValue;

//内部执行重绘操作

[selfsetNeedsDisplay];

self.valueLbl.text=[NSStringstringWithFormat:@"%.2f%%",(sliderValue100)];

}



#pragmamark-绘制下载进度条

-(void)drawRect:(CGRect)rect{

//1.获取上下文

CGContextRefcxtRef=UIGraphicsGetCurrentContext();

//2.创建路径

CGFloatstartA=-M_PI_2;

CGFloatendA=self.sliderValueM_PI2-M_PI_2;



UIBezierPathpath=[UIBezierPathbezierPathWithArcCenter:CGPointMake(150,150)radius:150startAngle:startAendAngle:endAclockwise:YES];



//保证绘制出来是扇形

[pathaddLineToPoint:CGPointMake(150,150)];

//3.添加路径

CGContextAddPath(cxtRef,path.CGPath);

//4.渲染

CGContextDrawPath(cxtRef,kCGPathFill);

}



@end

#import"ViewController.h"

#import"DownloadView.h"



@interfaceViewController()



/

下载进度的视图

/

@property(nonatomic,weak)IBOutletDownloadViewdownloadView;



@end



@implementationViewController



#pragmamark-滑动事件

-(IBAction)sliderValueChanged:(UISlider)sender{

NSLog(@"现在的值是%f",sender.value);

//传递值给自定义view

self.downloadView.sliderValue=sender.value;

}



@end



饼状图

思路:?构建数据,NSArraydata=@[@30,@15,@5,@17,@3,@10,@20];。?根据数据个数绘制“扇形”(弧)?注意:?每个弧的起始、结束弧度都是不一样的?每次绘制完毕一个弧以后都要重新设置下一次的起始弧度为当前的结束弧度?本次绘制的结束弧度,为起始弧度+本次的弧度

-(void)drawRect:(CGRect)rect{



//1.数据

NSArraydata=@[@30,@15,@5,@17,@3,@10,@20];



//1.2获取图形上下文

CGContextRefcxtRef=UIGraphicsGetCurrentContext();



//2.遍历

//2.0.1圆心,半径

CGPointcenter=CGPointMake(150,150);

CGFloatradius=120;

BOOLclockwise=YES;



//2.0.2定义起始角度的变量

CGFloatstartA=0;



for(NSIntegeri=0;i


//2.1取出数据,并转为int类型

floatnumber=[data[i]floatValue];



//2.2计算所占用的角度

CGFloatAngleOfNum=number/100(M_PI2);



//2.3计算结束角度

CGFloatendA=startA+AngleOfNum;



//2.4创建路径对象

UIBezierPathpath=[UIBezierPathbezierPathWithArcCenter:centerradius:radiusstartAngle:startAendAngle:endAclockwise:clockwise];



//2.4.2添加线

[pathaddLineToPoint:center];



//2.5添加路径

CGContextAddPath(cxtRef,path.CGPath);



//随机色

[[UIColorcolorWithRed:((float)arc4random_uniform(256)/255.0)green:((float)arc4random_uniform(256)/255.0)blue:((float)arc4random_uniform(256)/255.0)alpha:1.0]setFill];



//2.6渲染

CGContextDrawPath(cxtRef,kCGPathFill);



//2.7改变角度

startA=endA;

}

}



柱状图

1.构建数据,NSArraydata=@[@300,@150.65,@55.3,@507.7,@95.8,@700,@650.65];?2.根据数据的个数绘制柱状图。?3.计算每个柱子的x,y,w,h即可

#pragmamark-绘制柱形图

-(void)drawRect:(CGRect)rect{



//1.数据

NSArraydata=@[@300,@150.65,@55.3,@507.7,@95.8,@700,@650.65];





//2.获取图形上下文

CGContextRefcxtRef=UIGraphicsGetCurrentContext();



//计算宽度

CGFloatwidth=rect.size.width/(data.count2-1);





//3.遍历集合创建路径对象

for(inti=0;i


//计算x,y,高度

CGFloatx=i(width2);

CGFloatheight=[data[i]intValue]/1000.0rect.size.height;

NSLog(@"%f",height);

CGFloaty=rect.size.height-height;



//创建路径对象

UIBezierPathpath=[UIBezierPathbezierPathWithRect:CGRectMake(x,y,width,height)];



[[UIColorcolorWithRed:arc4random_uniform(256)/255.0green:arc4random_uniform(256)/255.0blue:arc4random_uniform(256)/255.0alpha:1.0]set];



//将路径对象添加到图形上下文中

CGContextAddPath(cxtRef,path.CGPath);



//渲染

CGContextDrawPath(cxtRef,kCGPathFillStroke);

}

}



Quartz2D内存管理

1>通过product->Analyze来进行内存分析?2>使用注意:对于C语言的框架,通过使用”create”“copy”“retain”函数创建的对象,使用完毕后都要进行释放?3>解决办法?CGPathRelease();//释放路径对象?CFRelease();//可以释放任何对象



-使用Path对象时的内存管理问题:?1>凡是遇到retain、copy、create出的对象,都需要进行release?2>但是CGPathCreateMutable()不是OC方法,所以不是调用某个对象的release方法?3>CGXxxxxCreate对应的就有CGXxxxxRelease。?4>通过CFRelease(任何类型);可以释放任何类型。

图片和文字绘制

-(void)drawRect:(CGRect)rect{



[selfimageDemo];

[selfstrDemo];

}



#pragmamark-图片的绘制

-(void)imageDemo{

//1.获取图片

UIImageimage=[UIImageimageNamed:@"me"];



//2.3种方式绘制

//-从某个点开始绘制图片

//[imagedrawAtPoint:CGPointZero];



//-在某个区域绘制图片

[imagedrawInRect:CGRectMake(100,100,200,300)];



//-以平铺的方式绘制图片

//[imagedrawAsPatternInRect:rect];

}



#pragmamark-绘制文字

-(void)strDemo{

//1.文字

NSStringstr=@"理想很丰满,现实很滑感";

//2.绘制

NSDictionarydict=@{

NSFontAttributeName:[UIFontsystemFontOfSize:20],

NSForegroundColorAttributeName:[UIColorredColor]

};



//MARK:-1.从某个点绘制文字!

//[strdrawAtPoint:CGPointMake(50,50)withAttributes:dict];



//MARK:-2.在某个区域绘制文字,并且会自动换行,如果超出范围,显示不全!

[strdrawInRect:CGRectMake(100,350,100,50)withAttributes:dict];

}



自定义UIImageView







剪裁原型图片设置个人中心个性头像

-(void)drawRect:(CGRect)rect{



//1.获取图形上下文

CGContextRefcxtRef=UIGraphicsGetCurrentContext();



//MARK:-2.在添加被裁剪路径之前,有别的内容被渲染了,之前渲染的内容是否能够显示?

UIBezierPathround2=[UIBezierPathbezierPathWithOvalInRect:CGRectMake(100,100,100,100)];

//添加别的路径

CGContextAddPath(cxtRef,round2.CGPath);

//设置线宽

CGContextSetLineWidth(cxtRef,10);

//设置线条颜色

[[UIColorwhiteColor]setStroke];

//渲染

CGContextDrawPath(cxtRef,kCGPathStroke);





//2.创建一个要裁剪的图形的路径【圆形】

CGPointcenter=CGPointMake(150,150);

CGFloatradius=50;

CGFloatstartA=0;

CGFloatendA=M_PI2;

BOOLclockwise=YES;



UIBezierPathpath=[UIBezierPathbezierPathWithArcCenter:centerradius:radiusstartAngle:startAendAngle:endAclockwise:clockwise];



//3.将圆形的路径添加到图形上下文中[不能渲染]

CGContextAddPath(cxtRef,path.CGPath);



//MARK:-1.路径被渲染了,是否还能够裁剪?

//裁剪就达不到效果了!

//CGContextDrawPath(cxtRef,kCGPathStroke);



//4.裁剪!

CGContextClip(cxtRef);



//5.把图片画上去

[[UIImageimageNamed:@"me"]drawAtPoint:CGPointMake(100,100)];

}



剪裁图片赋值到imageview上,并保存到沙盒或者相册

#pragmamark-点击裁剪按钮调用的!

-(IBAction)clipBtnClick:(UIButton)sender{



//0.图片

UIImageimage=[UIImageimageNamed:@"me"];





//1.需要开启图片的图形上下文

/

size开启的图形上下文的大小

opaque不透明!YES[不透明,四个角是黑色的!],NO[透明]->NO

scale屏幕的缩放因子!0.0->直接匹配当前设备屏幕的缩放因子!

/

UIGraphicsBeginImageContextWithOptions(image.size,NO,0.0);



//2.获取当前的图形上下文!【图片的图形上下文】

CGContextRefcxtRef=UIGraphicsGetCurrentContext();



//3.创建一个圆形的路径

//椭圆->圆形!

UIBezierPathpath=[UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0,image.size.width,image.size.height)];



//4.将圆形路径添加到图形上下文

CGContextAddPath(cxtRef,path.CGPath);



//5.裁剪

CGContextClip(cxtRef);



//6.把图片绘制出来

[imagedrawAtPoint:CGPointZero];



//7.从当前的图形上下文中获取图片

UIImageclipImg=UIGraphicsGetImageFromCurrentImageContext();



//8.把图片的图形上下文进行关闭

UIGraphicsEndImageContext();



//MARK:-展示图片

UIImageViewimgView=[[UIImageViewalloc]initWithImage:clipImg];



imgView.center=CGPointMake(100,200);



[self.viewaddSubview:imgView];





//MARK:-1.保存图片到沙盒!

//1.沙盒路径

NSStringfilePath=[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES)lastObject]stringByAppendingPathComponent:@"xxx.png"];



//2.把图片存进去

//2.1需要将图片转为NSData类型数据

NSDatadata=UIImagePNGRepresentation(clipImg);



//2.2将二进制数据写入文件,就可以了!

[datawriteToFile:filePathatomically:YES];



//MARK:-1.保存图片到相册!

/

image:要保存的图片

completionTarget:存储结束后,监听的对象!

completionSelector:存储结束后,监听的对象需要执行的方法!

contextInfo:上下文信息,可以写字符串,或中nil,最大的作用:可以帮助区分是哪个图片被存进去了!



//第一次进行图片存储时,会提醒用户,应用要访问相册,需要用户的许可,才可以存储!

//以后就不会再进行提示了!可以通过设置里面进行权限修改!

/

//UIImageWriteToSavedPhotosAlbum(clipImg,nil,nil,nil);



UIImageWriteToSavedPhotosAlbum(clipImg,self,@selector(image:didFinishSavingWithError:contextInfo:),@"touxiang");

}



/

@paramimage存储的图片

@paramerror错误信息,如果存储出错,会返回对应的错误信息!

@paramcontextInfo上下文信息,上传什么,这里就是什么

/

-(void)image:(UIImage)imagedidFinishSavingWithError:(NSError)errorcontextInfo:(void)contextInfo{



if(error){

NSLog(@"出错了%@",error);

return;

}

NSLog(@"存储成功%@",contextInfo);



}



文字水印和图片水印绘制

1、添加文字水印

1>创建位图上下文?2>把图片画上去?3>把文字画上去?4>从上下文中取出图片

2、添加图片水印

1>创建位图上下文?2>把图片画上去?3>加载logo图片(水印图片),把水印图片也画上去?4>从上下文中取出图片

#pragmamark-文字水印/图片水印绘制

-(void)demo2{



//1.开启图片的图形上下文

UIGraphicsBeginImageContextWithOptions(CGSizeMake(300,400),NO,0.0);



//2.获取当前的图形上下文

//CGContextRefcxtRef=UIGraphicsGetCurrentContext();



//3.将littleDog绘制上去!

[[UIImageimageNamed:@"littledog"]drawInRect:CGRectMake(0,0,300,400)];



//4.将文字绘制上去!

[@"旺旺旺旺"drawAtPoint:CGPointMake(100,100)withAttributes:@{

NSForegroundColorAttributeName:[UIColormagentaColor],

NSFontAttributeName:[UIFontsystemFontOfSize:30]



}];



//4.绘制图片水印

[[UIImageimageNamed:@"logo"]drawAtPoint:CGPointMake(100,200)];





//5.从当前上下文中取出图片

UIImagetextImg=UIGraphicsGetImageFromCurrentImageContext();



//6.关闭图形上下文

UIGraphicsEndImageContext();



//7.展示图片

UIImageViewimgView=[[UIImageViewalloc]initWithImage:textImg];



imgView.center=self.view.center;



[self.viewaddSubview:imgView];

}





屏幕截屏

核心代码?-(void)renderInContext:(CGContextRef)ctx;?调用某个view的layer的renderInContext:方法即可

截图基本思路:?1、获取控件的layer对象?2、调用layer对象的renderInContext:方法渲染到上下文中?注意:UISegmentedControl渲染时有问题

#pragmamark-截图按钮被点击

-(IBAction)btnClick:(id)sender{



dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(0.5NSEC_PER_SEC)),dispatch_get_main_queue(),^{



//1.开启图片的图形上下文

UIGraphicsBeginImageContextWithOptions(self.view.bounds.size,NO,0.0);



//2.获取图形上下文

CGContextRefcxtRef=UIGraphicsGetCurrentContext();



//3.将视图的layer【层】渲染[render]到上下文中

[self.view.layerrenderInContext:cxtRef];



//4.获取图片

UIImageimage=UIGraphicsGetImageFromCurrentImageContext();



//5.关闭上下文

UIGraphicsEndImageContext();



//6.保存到相册

UIImageWriteToSavedPhotosAlbum(image,nil,nil,nil);

});

}

献花(0)
+1
(本文系网络学习天...首藏)