CGContextRef
系统会维护一个 CGContextRef 的栈,而 UIGraphicsGetCurrentContext()会取栈顶的CGContextRef,正确的做法是只在 drawRect 里调用 UIGraphicsGetCurrentContext(),因为在 drawRect 之前,系统会往栈里压入一个 valid(有效的)CGContextRef,除非自己去维护一个CGContextRef,否咋不应该在其他地方取CGContextRef
Quartz2D 自定义控件
图形上下文 Graphics Context 是一个 CGContextRef 类型数据
保存绘图信息,绘图状态,决定绘制的输出目标
绘制好的图形 保存-> 图形上下文 显示-> 输出目标
自定义控件前要把图形上下文指定到 Layer 上,那个图形上下文必须和 view 相关联
1️⃣ 新建一个类,继承 UIView
2️⃣ 实现drawRect: 在这个方法中才能取得跟 view 相关的上下文
来之 Core Graphics 框架,纯 C 语言,CG开头
画线:
1️⃣ 新建继承 UIView 类的 View
获取图形上下文 CGContextRef ctx = UIGraphicsGetCurrentContext(); 获取到 layer Graphics Context
2️⃣ 绘制图形 两点决定一条线段
↪️ 设置起点
CGContextMoveToPoint(ctx,20,20); 移动到这个点,把这个点设置成起点
↪️ 设置线段终点
CGContextAddLineToPoint(ctx,100,100); 设置终点,这样有线段了
↪️ 再设置一个终点就自动接上
↪️ 设置绘图状态(比如加粗,想要修改的话必须在渲染之前完成)
CGContextSetLineWidth(ctx,20); 设置什么就以 Set 查询
↪️ 设置颜色
CGContextSetRGBStrokeColor(ctx,red,green,blue,alpha);
↪️ 设置线段头部形状
CGContextSetLineCap(ctx,CGLineCapRound); //cap -> 帽子的意思
↪️ 设置转角的形状
CGContextSetLineJoin(ctx,kCGLineRound); //Join -> 连接
3️⃣ 讲图形上下文保存的图形信息渲染到 view 上
CGContext
StrokePath(ctx); 空心的方式渲染(对应的有实心的渲染方式 Fill)
要想绘制两个不相连接的线段,要设置两个起点,第两个起点之前要先把第一个绘制出来
画图形
1️⃣ 三角形
绘制出两个线段后,可以直接关闭路径,把起点和重点合拢
CGContextClosePath(ctx);
2️⃣四边形
告诉图形上下文绘制一个四边形
CGContextAddRect(ctx,CGRectMake());
实心的:
1️⃣ CGContextFillPath(ctx); 把 Strock 替换成 Fill 就渲染成实心的
设置颜色也要对应的实心,否咋没效果
CGContextFillPath(ctx);
[[UIColor redColor] setFill]; 快捷设置
[[UIColor redColor] set]; 更快捷
1️⃣ 画圆形
确定一个矩形范围
CGContextAddEllipseInRect(ctx,CGRectMake());
1️⃣ 画圆弧
CGContextAddArc(ctx,x,y,,radius,startAngle,endAngle,cloclwise) //x,y 圆心, radius 半径, 开始和结束角度(默认有水平线参考,起始角度为0°,往左为-°) clockwise 顺时针(0)还是逆时针(1),
1️⃣ 画1/4图形
先画一条线,从线的终点开始在画一个弧,在从弧的终点画线(关闭路径)
1️⃣ 画文字
CGContextShowText()....过时了,有缺点,不支持中文,且文字是倒的(坐标系不同)
NSString *str = @"MacBook";
[str drawAtPoint:CGPointZero WithAttributes:nil]; //绘制到0,0坐标上了
WithAttributes:要求字典类型,
dict[NSFontAttributeName] = [UIFont ...]; //字体大小
dict[NSForegroundColorAttributeName] = [UIColor ...]; //字体颜色
dict[NSBackGroundColorAttributeName] = [UIColor ..]; 文字所占区域颜色
↪️ [str drawInRect:WithAttributes:]; 绘制到指定区域(可自动换行)
1️⃣ 画图片
C 方法也是倒的
1️⃣ 加载图片 UIImage
2️⃣ 绘制 drawAtPoint: 按照原有比例
↪️ drawInRect: 绘制到什么范围,图片会被拉伸
↪️ drawAsPatternInRect: 平铺(可制作网格背景,优化内存)
水印(假的,Layer上)
画文字
drawAtPoint:
贝塞尔曲线:
3个点,开始点,控制点,结束点
moveTo 开始点
CGContextAddQuadCuerveToPoint(ctx,cpx/y 控制点,结束点);
图形上下文栈 stark
原理 :为什么画第二条线段的时候属性设置的是第一条的(颜色,粗细)
调用绘图渲染后就立马查看绘图状态(颜色,粗细等)这样两条线属性是一样的
重置设置状态就把之前的状态覆盖或者保存一下之前的状态
拷贝图形上下栈 CGContextSaveGState(ctx);存储在栈中
读取保存的图形上下栈 CGContextRestoreGState(ctx); 删除之前的图形栈,使用保存的栈
绘制歪的四边形
CGContextAddRect 缺点只能是正的
设置矩阵 旋转-缩放-平移
CGContextRoateCTM(ctx,弧度); 整个屏幕都是歪的
scaleCTM: 缩放比例(0.5,0.5) view整体缩放
translateCTM 移动的距离,不是坐标
同样要在绘制之前设置
剪切图片(头像)
1️⃣ drawInRect:
CGContextAddEllipseInRect: 要剪切的范围
CGContextClip 剪切
CGContextFillPath 绘制 这两句话顺序不能错
2️⃣ 先画源,在告诉ctx 只显示圆面积的范围,在添加图片
总结:先画出要显示的图形,在添加图片,超出的范围就不会显示
自定义 imageView
1️⃣ 自定义 imageView继承 ImageView
2️⃣ drawInRect 加载图片
3️⃣ 设置一个 image属性,画的时候使用 image 大小
使用的时候创建 自定义的 imageview,把图片赋值给image属性,绘制
但是这样有 BUG,切换图片的时候无法切换,应为 drawRect 只调用一次:第一次显示调用或调用文档中的两个方法时才又调用
所以在切换按钮中先设置要显示的图片然后调用文档中的
setNeedsDisplay 方法
↪️ 直接重写 setImage 方法
总结:setNeedsDisplay 重新全部渲染
setNeedsDisplayInRect 局部渲染
可以制作动画: 1️⃣ 加载图片,渲染
2️⃣ drawRect 里无法调用自己刷新自己的方法,需要定时器
3️⃣ awakeFromNib 里面开启定时器 NSTimer 刷帧效果不好
CADisplayLink 刷帧定时器, displayLinkWithTarget: 默认1秒60次,需要手动添加到消息事件中,link addToRunLoop:[[NSRunLoop mainRunLoop] NSDefaultRunLoopMode]
定时器总结:
NSTimer 定时更新一些数据(资料) 不准确
CADisplayLink 更新 View 做一些动画的时候使用,准确,不准确的时候屏幕会花掉
第二天
画四边形
1️⃣ 四个点
2️⃣ 画线然后设置宽度
3️⃣ 直接画矩形
4️⃣ 二合一 CGContextFillRect
5️⃣ OC 方法 UIRectFill
绘图路径
CGMutablePathRef path = CGPathCreatMutable(); 专门保存绘图的路径
以前是系统自动创建的,可以手动取出来
CGPathMoveToPoint(path,NULL,0,0); //设置起点
CGPathAddLineToPoint(path,NULL,100,20); 设置终点
目前只有路径,还是要先获取上上下文,添加绘图路径到上下文
CGContextAddPath(ctx,path);
ARC 通过 C 语言函数创建的对象,如果函数包含 Creat/Retain/Copy 必须要 手动 release
CGPathRelease(path); 释放路径 (CFRelease(path))
图片水印(画在图片上)
生成一张全新的图片
渲染到哪里由图形上下文决定
拿到 bitmap 上下文,拿不到系统的,要自己创建
新建一个基于位图的上下文
UIGraphicsBeginImageContextWithOptions(新图片大小,是否透明(YES 不透明),缩放比例)
关闭上下文 UIGraphicsEndImageContext();
保存二进制 NSData UIImagePNGRepresentation(newImage);
data writeToFile:
最好动态指定路径
类别 UIimage+ZB
1️⃣ 加载背景图片
2️⃣ 创建 bitmap 上下文
3️⃣ 画背景图片
4️⃣ 取出图片
5️⃣ 显示生成的新图片
图片裁剪
绘制到图片中,直接创建图片上下文,不用 DrawRect 方法
1️⃣ 创建上下文,和图片大小一样,相当于生成了一张新的图片模板
2️⃣ 指定可绘制的区域 画圆 指定裁剪范围 CGContextClip(ctx)
3️⃣ 绘制图片 drawInRect
4️⃣ 取出绘制好的图片 UIGraphicsGetImageFromCurrentImageContext();
5️⃣ 关闭上下文
6️⃣ 显示图片
7️⃣ 保存文件
屏幕截图
保存 Layer
1️⃣ 创建 bitmap 上下文,view 大小
2️⃣ 拿到控制器的 layer renderInRect:
3️⃣ 取出图片
4️⃣ NSData UIImagePNGRepresentation
总结:可以创建一个新的 view 就可以指定截图区域(view 嵌套得到小 view)
Quratz2D 应用---电子书
图片可生成 Color
colorWithPatternImage:
self.view.backgroundColor = color;
原理: 创建一个矩形,在矩形上画一条线,在生成一张图片,平铺;
1️⃣ 创建bitmap,
2️⃣ 绘制矩形
↪️ 画线
3️⃣ 获取图片
4️⃣ 设置背景
当 view 可以滚动时,图片不知道要多长,绘制就可以解决
TextView
阅读器-翻页
1️⃣ 定义索引,记录第几页
CATranstion
.type = @"PageCul";
1️⃣ 改变索引
2️⃣ 生成新内容
3️⃣ 设置新内容
4️⃣ 创建动画
5️⃣ 执行动画
.layer animation: forKey:nil
#endif