一、绘图的几种方式
1.最原始的绘图方式
// 1.获取图形上下文
// 目前我们所用的上下文都是以UIGraphics
// CGContextRef Ref:引用 CG:目前使用到的类型和函数 一般都是CG开头 CoreGraphics
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 2.描述路径
// 创建路径
CGMutablePathRef path = CGPathCreateMutable();
// 设置起点
// path:给哪个路径设置起点
CGPathMoveToPoint(path, NULL, 50, 50);
// 添加一根线到某个点
CGPathAddLineToPoint(path, NULL, 200, 200);
// 3.把路径添加到上下文
CGContextAddPath(ctx, path);
// 4.渲染上下文
CGContextStrokePath(ctx);
2.绘图的第二种方式
// 获取上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 描述路径
// 设置起点
CGContextMoveToPoint(ctx, 50, 50);
CGContextAddLineToPoint(ctx, 200, 200);
// 设置绘图状态,一定要在渲染之前
// 颜色
[[UIColor redColor] setStroke];
// 线宽
CGContextSetLineWidth(ctx, 5);
// 设置连接样式
CGContextSetLineJoin(ctx, kCGLineJoinBevel);
// 设置顶角样式
CGContextSetLineCap(ctx, kCGLineCapRound);
// 渲染上下文
CGContextStrokePath(ctx);
3.绘图的第三种方式
// UIKit已经封装了一些绘图的功能
// 贝瑟尔路径
// 创建路径
UIBezierPath *path = [UIBezierPath bezierPath];
// 设置起点
[path moveToPoint:CGPointMake(50, 50)];
// 添加一根线到某个点
[path addLineToPoint:CGPointMake(200, 200)];
[[UIColor greenColor] set];
path.lineWidth = 3;
// 绘制路径
[path stroke];
二、花圆弧
// 圆弧
// Center:圆心
// startAngle:弧度
// clockwise:YES:顺时针 NO:逆时针
// 扇形
CGPoint center = CGPointMake(125, 125);
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:100 startAngle:0 endAngle:M_PI_2 clockwise:YES];
// 添加一根线到圆心
[path addLineToPoint:center];
[path stroke];
// 填充:必须是一个完整的封闭路径,默认就会自动关闭路径
// [path fill];
三、画矩形
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(x, y, w, h)];
[[self colorRandom] set];
[path fill];
- (UIColor *)colorRandom
{
// 0 ~ 255 / 255
// OC:0 ~ 1
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];
}
四、绘制文字和图片
1.绘制普通文字
// 绘制文字
NSString *str = @"asfdsfsdfasfdsfsdfasfdsfsdfasfdsfsdfasfdsfsdfasfdsfsdfasfdsfsdfasfdsfsdfasfdsfsdfasfdsfsdfasfdsfsdfasfdsfsdfasfdsfsdf";
// 不会换行
// [str drawAtPoint:CGPointZero withAttributes:nil];
[str drawInRect:self.bounds withAttributes:nil];
2.绘制富文本文字
// 绘制文字
NSString *str = @"asfdsfsdf";
// 文字的起点
// Attributes:文本属性
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];
3.绘制图片
// 超出裁剪区域的内容全部裁剪掉
// 注意:裁剪必须放在绘制之前
UIRectClip(CGRectMake(0, 0, 50, 50));
UIImage *image = [UIImage imageNamed:@"001"];
// 默认绘制的内容尺寸跟图片尺寸一样大
// [image drawAtPoint:CGPointZero];
// [image drawInRect:rect];
// 绘图
[image drawAsPatternInRect:rect];
五、图形上下文状态栈
// 如果以后用贝瑟尔绘制图形【path stroke】,上下文的状态由贝瑟尔路径状态
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
// 1.获取上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 2.描述路径
// 第一根
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(10, 125)];
[path addLineToPoint:CGPointMake(240, 125)];
// 把路径添加到上下文
// .CGPath 可以UIkit的路径转换成CoreGraphics路径
CGContextAddPath(ctx, path.CGPath);
// 保存一份上下文的状态
CGContextSaveGState(ctx);
// 设置上下文状态
CGContextSetLineWidth(ctx, 10);
[[UIColor redColor] set];
// 渲染上下文
CGContextStrokePath(ctx);
// 第二根
// 2.描述路径
// 第一根
path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(125, 10)];
[path addLineToPoint:CGPointMake(125, 240)];
// 把路径添加到上下文
// .CGPath 可以UIkit的路径转换成CoreGraphics路径
CGContextAddPath(ctx, path.CGPath);
// 还原状态
CGContextRestoreGState(ctx);
// // 设置上下文状态
// CGContextSetLineWidth(ctx, 1);
//
// [[UIColor blackColor] set];
// 渲染上下文
CGContextStrokePath(ctx);
}
六、矩阵操作
- (void)drawRect:(CGRect)rect {
// 1.获取上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 2.描述路径
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);
// 3.把路径添加上下文
CGContextAddPath(ctx, path.CGPath);
[[UIColor redColor] set];
// 4.渲染上下文
CGContextFillPath(ctx);
}
七、位图上下文
1.图片水印
// 加载图片
UIImage *image = [UIImage imageNamed:@"小黄人"];
// 0.获取上下文,之前的上下文都是在view的drawRect方法中获取(跟View相关联的上下文layer上下文)
// 目前我们需要绘制图片到新的图片上,因此需要用到位图上下文
// 怎么获取位图上下文,注意位图上下文的获取方式跟layer上下文不一样。位图上下文需要我们手动创建。
// 开启一个位图上下文,注意位图上下文跟view无关联,所以不需要在drawRect.
// size:位图上下文的尺寸(新图片的尺寸)
// opaque: 不透明度 YES:不透明 NO:透明,通常我们一般都弄透明的上下文
// scale:通常不需要缩放上下文,取值为0,表示不缩放
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);
// // 1.获取上下文(位图上下文)
// CGContextRef ctx = UIGraphicsGetCurrentContext();
//
// // 2.描述路径
// CGContextMoveToPoint(ctx, 50, 50);
//
// CGContextAddLineToPoint(ctx, 200, 200);
//
// [[UIColor redColor] set];
//
// // 3.渲染上下文
// CGContextStrokePath(ctx);
UIBezierPath *path =[UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 300, 300)];
[[UIColor redColor] set];
[path stroke];
// // 1.绘制原生的图片
// [image drawAtPoint:CGPointZero];
//
// // 2.给原生的图片添加文字
// NSString *str = @"小码哥";
//
// // 创建字典属性
// NSMutableDictionary *dict = [NSMutableDictionary dictionary];
// dict[NSForegroundColorAttributeName] = [UIColor redColor];
// dict[NSFontAttributeName] = [UIFont systemFontOfSize:20];
//
// [str drawAtPoint:CGPointMake(200, 528) withAttributes:dict];
// 3.生成一张图片给我们,从上下文中获取图片
UIImage *imageWater = UIGraphicsGetImageFromCurrentImageContext();
// 4.关闭上下文
UIGraphicsEndImageContext();
_imageView.image = imageWater;
2.图片裁剪
// 0.加载图片
UIImage *image = [UIImage imageNamed:@"阿狸头像"];
// 1.开启位图上下文,跟图片尺寸一样大
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);
// 2.设置圆形裁剪区域,正切与图片
// 2.1创建圆形的路径
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
// 2.2把路径设置为裁剪区域
[path addClip];
// 3.绘制图片
[image drawAtPoint:CGPointZero];
// 4.从上下文中获取图片
UIImage *clipImage = UIGraphicsGetImageFromCurrentImageContext();
// 5.关闭上下文
UIGraphicsEndImageContext();
_imageView.image = clipImage;
3.屏幕截屏
+ (UIImage *)imageWithCaputureView:(UIView *)view
{
// 开启位图上下文
UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0);
// 获取上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 把控件上的图层渲染到上下文,layer只能渲染
[view.layer renderInContext:ctx];
// 生成一张图片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// 关闭上下文
UIGraphicsEndImageContext();
return image;
}
UIImage *image = [UIImage imageWithCaputureView:self.view];
// image转data
// compressionQuality: 图片质量 1:最高质量
NSData *data = UIImageJPEGRepresentation(image,1);
[data writeToFile:@"/Users/xiaomage/Desktop/view.png" atomically:YES];
4.图片截取
- (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;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// 给控制器的view添加一个pan手势
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);
// 生成截屏的view
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];
// 截取的view设置为nil
_clipView = nil;
}
5.屏幕擦除
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
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();
// 控件的layer渲染上去
[_imageView.layer renderInContext:ctx];
// 擦除图片
CGContextClearRect(ctx, rect);
// 生成一张图片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
_imageView.image = image;
// 关闭上下文
UIGraphicsEndImageContext();
}