Quartz2D
- 在 - (void)drawRect:(CGRect)rect方法里面实现添加一个根线
- 基本步骤
- 1.获取上下文->2.描述路径->3.把路径添加到上下文->4.把上下文的内容渲染到View的layer.
//作用:绘图(该方法是UIView的方法,所以凡是UIView的子类都拥有,都可以实现)
//什么时候调用:(系统自动调用)当View显示的时候调用
//参数:当前View的bounds
//在drawRect系统已经自动创建了一个跟当前View相关联的上下文
- (void)drawRect:(CGRect)rect {
//1.获取跟View相关联的上下文(uigraphics开头)
// CGContextRef ctx = UIGraphicsGetCurrentContext();
//2.描述路径
// UIBezierPath *path = [UIBezierPath bezierPath];
//设置起点
// [path moveToPoint:CGPointMake(50, 250)];
//添加一根曲线到某个点
// [path addQuadCurveToPoint:CGPointMake(250, 250) controlPoint:CGPointMake(80, 100)];
//3.把路径添加到上下文
// CGContextAddPath(ctx, path.CGPath);
//4.把上下文内容渲染到View上.
// CGContextStrokePath(ctx);
//在drawRect系统已经自动创建了一个跟当前View相关联的上下文,所以只要添加上路径就可以了
UIBezierPath *path = [UIBezierPath bezierPath];
//设置起点
[path moveToPoint:CGPointMake(50, 150)];
//添加一根线到某个点
[path addLineToPoint:CGPointMake(250, 50)];
[path setLineWidth:10];
[path setLineCapStyle:kCGLineCapRound];
[[UIColor redColor] set];
[path stroke];
// 自定义的方法中是实现添加一根线
// [self drawLine];
}
//画直线(也可以画曲线)
- (void)drawLine {
//1.获取跟View相关联的上下文(uigraphics开头)
CGContextRef context = UIGraphicsGetCurrentContext();
//2.描述路径
//一条路径可以绘制多条线
UIBezierPath *path = [UIBezierPath bezierPath];
//设置起点
[path moveToPoint:CGPointMake(50, 150)];
//添加一根线到某个点
[path addLineToPoint:CGPointMake(250, 50)];
//画第二根线
//[path moveToPoint:CGPointMake(50, 250)];
//[path addLineToPoint:CGPointMake(250, 100)];
//把上一条路径的终点,当作是下一个路径的起点
[path addLineToPoint:CGPointMake(50, 250)];
//设置上下文的状态
// 设置线宽
CGContextSetLineWidth(context, 10);
//设置线的连接样式
CGContextSetLineJoin(context, kCGLineJoinMiter);
//设置线的顶角样式
CGContextSetLineCap(context, kCGLineCapRound);
//设置颜色(Sets the fill and stroke colors in the current drawing context.)
[[UIColor redColor] set];
//3.把路径添加到上下文
//UIBezierPath->UIKit --> CGPathRef->CoreGraphics
CGContextAddPath(context, path.CGPath);
//4.把上下文当中绘制的内容渲染到跟View关联的layer.(stroke ,fill)
CGContextStrokePath(context);
}
- (void)drawRect:(CGRect)rect {
//描述一个椭圆
//UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(50, 50, 200, 200)];
//绘制路径
//[[UIColor yellowColor] set];
//[path fill];
//画弧
//Center:弧所在的圆心
//radius:圆的半径
//startAngle:开始角度,圆的最右侧为0度
//endAngle:截至角度,向下为正,向上为负.
//clockwise:时针的方向,yes:顺时针 no:逆时针
//CGPoint center = CGPointMake(rect.size.width * 0.5, rect.size.height * 0.5);
CGFloat radius = rect.size.width * 0.5 - 10;
CGFloat startA = 0;
CGFloat endA = -M_PI_2;
//画弧的路径
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:self.center radius:radius startAngle:startA endAngle:endA clockwise:NO];
//画扇形
//添加一根线到圆心
[path addLineToPoint:self.center];
//关闭路径(自动的从路径的终点连接到路径的起点)
//[path closePath];
[[UIColor redColor] set];
//使用fill在填充之前,自动的关闭路径
[path fill];
//1.获取上下文->2.描述路径->3.把路径添加到上下文->4.把上下文的内容渲染到View的layer.
}
//画矩形
- (void)drawRect {
//1.获取上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
//2.描述路径
//矩形
//UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(50, 50, 200, 200)];
//画圆角矩形
//cornerRadius:圆角半径
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(50, 50, 200, 200) cornerRadius:100];
//3.把路径添加到上下文
CGContextAddPath(ctx, path.CGPath);
[[UIColor redColor] set];
//4.把上下文的内容渲染到View的layer.
//CGContextStrokePath(ctx);
CGContextFillPath(ctx);
}
b贝曲尔曲线画饼图
- 步骤
- 设置圆心的位置center(CGPoint)
- 设置开始的角度startAngle(CGFloat),这其中涉及到数字转换为角度(num.intValue / 100.0 * M_PI * 2;)
- 使用贝曲尔曲线画圆
- (void)drawRect:(CGRect)rect {
// Drawing code
NSArray *dataArray = @[@25,@25,@50];
//画弧
CGPoint center = CGPointMake(rect.size.width * 0.5, rect.size.height * .5);
CGFloat radius = rect.size.width * 0.5 - 10;
// 初始化角度
CGFloat startA = 0;
CGFloat angle = 0;
CGFloat endA = 0;
// 从数组中读取到每个圆所占的比例
for (NSNumber *num in dataArray) {
startA = endA;
//转换为角度
angle = num.intValue / 100.0 * M_PI * 2;
endA = startA + angle;
// 使用贝曲尔曲线画圆
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES];
// 曲线的颜色
[[self randomColor] set];
//添加一根线到圆心
[path addLineToPoint:center];
// 自动闭合
[path fill];
}
}
雪花效果
- (void)awakeFromNib {
//添加定时器
//[NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(update) userInfo:nil repeats:YES];
//什么时候调用指定的方法?
//当下一次屏幕刷新时调用(屏幕每一秒刷新60)
CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(update)];
//想要让CADisplayLink工作, 必须得要添加到主运行循环当中.
[link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
//setNeedsDisplay底层会调用drawRect,并不是立马调用的.只是设了一个调用的标志.
//等下一次屏幕刷新时才去调用drawRect
}
static int _snowY = 0;
- (void)update {
_snowY += 10;
if (_snowY > self.bounds.size.height) {
_snowY = 0;
}
//重绘
[self setNeedsDisplay];
}
// 三个方法的调用顺序:
// 首先会调用awakeFromNib,在里面设置屏幕的刷新率,然后在显示view的时候调用了drawRect:(CGRect)rect方法,添加了一张雪花的图片,然后屏幕在刷新的时候调用了update 的方法,每一次调用的时候都会进行重绘,重绘时又调用drawRect:(CGRect)rect 方法更新图片的y 位置
- (void)drawRect:(CGRect)rect {
//加载图片
UIImage *image = [UIImage imageNamed:@"雪花"];
[image drawAtPoint:CGPointMake(0, _snowY)];
}
图片加水印
- 不仅图片可以绘画到图形上下文中,NSString字符串也可以
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor yellowColor];
//生成一张图片
//0.加载图片
UIImage *oriImage = [UIImage imageNamed:@"小黄人"];
//1.创建位图上下文(size:开启多大的上下文,就会生成多大的图片)
UIGraphicsBeginImageContext(oriImage.size);
//2.把图片绘制到上下文当中
[oriImage drawAtPoint:CGPointZero]; // CGPointZero 在没有完全确定位置的时候用CGPointZero代替
//3.绘制水印
NSString *str = @"小黄人";
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[NSFontAttributeName] = [UIFont systemFontOfSize:20];
dict[NSForegroundColorAttributeName] = [UIColor redColor];
[str drawAtPoint:CGPointZero withAttributes:dict];
//4.从上下文当中生成一张图片
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
//5.关闭位图上下文
UIGraphicsEndImageContext();
self.imageV.image = newImage;
}
利用贝曲尔曲线和图形上下文裁剪图片
- (void)viewDidLoad {
[super viewDidLoad];
//生成一张圆形图片
//0.加载图片
UIImage *oriImage = [UIImage imageNamed:@"阿狸头像"];
//1.开启一个和图片一样大小的位图上下文
UIGraphicsBeginImageContext(oriImage.size);
//2.设置一个裁剪区域(圆形),从左上角开始,
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, oriImage.size.width, oriImage.size.height)];
//把路径设置成裁剪区域(超过裁剪区域以外的内容会自动被裁剪掉)
[path addClip];
//3.把图片绘制到上下文当中
[oriImage drawAtPoint:CGPointZero];
//4.从上下文当中生成一张图片
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
//5.关闭上下文
UIGraphicsEndImageContext();
self.imageV.image = newImage;
}
图片截屏
- (IBAction)pan:(UIPanGestureRecognizer *)pan {
//获取当前手指所在的点
CGPoint curP = [pan locationInView:self.imageV];
//判断手势的状态
if(pan.state == UIGestureRecognizerStateBegan) {
//记录当前手指的开始点
self.startP = curP;
} else if(pan.state == UIGestureRecognizerStateChanged) {
//rect
CGFloat w = curP.x - self.startP.x;
CGFloat h = curP.y - self.startP.y;
CGRect rect = CGRectMake(self.startP.x, self.startP.y, w, h);
self.coverView.frame = rect;
}else if(pan.state == UIGestureRecognizerStateEnded) {
//生成一张图片
UIGraphicsBeginImageContext(self.imageV.bounds.size);
//设置裁剪区域
UIBezierPath *path = [UIBezierPath bezierPathWithRect:self.coverView.frame];
[path addClip];
//2.把UIImageV当中的内容渲染到上下文当中
CGContextRef ctx = UIGraphicsGetCurrentContext();
[self.imageV.layer renderInContext:ctx];
//从上下文当中获取图片
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
//关闭上下文
UIGraphicsEndImageContext();
self.imageV.image = newImage;
[self.coverView removeFromSuperview];
}
}