71-Swift之上下文(CGContext)的介绍和图形绘制使用

前言

上下文(CGContext) 是图形绘制前,场景的布置对象。在App的开发中,图形的绘制也是基本的技能。图形绘制的选择要求开发者根据实际情况选择不同的绘制方式。今天我们带来的是 CGContext的绘制。

CGContext 的绘制图形

1、绘制虚线

// MARK: 绘制虚线
func drawDottedLine(rect: CGRect,context:CGContext) -> Void {
    // 设置绘制的颜色
    UIColor.red.set()
    // 设置宽度
    context.setLineWidth(10)
    // 设置起始点
    context.move(to: CGPoint.init(x: 10, y: 50))
    // 添加绘制路径点
    context.addLine(to: CGPoint.init(x: 200, y: 50))
    /**
     绘制虚线
     
     @phase : 虚线起始线段的长度偏差,则第一段的长度为: lengths[0] - phase
     @lengths : 一个存放虚线间隔和绘制长度的数组
     */
    context.setLineDash(phase: 10, lengths: [10,20,30])
    // 必和路径
    context.strokePath()
}
效果如下图:
88F0F6A3-F801-4456-9AD2-4C7C46873024.png

2、绘制曲线

// MARK: 绘制曲线
func drawCurve(rect: CGRect,context:CGContext) -> Void {
    // 设置绘制的颜色
    UIColor.red.set()
    // 设置宽度
    context.setLineWidth(5)
    // 设置起始点
    context.move(to: CGPoint.init(x: 10, y: 50))
    /**
     两点控制曲线
     
     to : 曲线的结束点
     control1 : 曲线控制点一。
     control2 : 曲线控制点二
     例子:
     context.addCurve(to: CGPoint.init(x: 250, y: 180), control1: CGPoint.init(x: 100, y: 200), control2: CGPoint.init(x: 200, y: 70))

     */
    /**
     单点控制曲线
     
     to : 曲线的结束点
     control: 曲线的控制点
     */
    context.addQuadCurve(to: CGPoint.init(x: 250, y: 180), control: CGPoint.init(x: 100, y: 200))
    // 必和路径
    context.strokePath()
}
效果图如下
A9079F58-0173-410B-915D-FB2E2FE8A149.png

A978A3FF-9108-4ABD-870B-04BCB170F78C.png

3、 绘制四变形

// MARK: 绘制四变形
func drawRect(rect: CGRect,context:CGContext) -> Void {
    // 设置绘制的颜色
    UIColor.red.set()
    // 设置宽度
    context.setLineWidth(5)
    /**
     设置绘制四边形的大小,通过控制长和宽绘制长方形和正方形
     
     @ x : 四边形的起点X轴的位置。
     @ y : 四边形的起点Y轴的位置。
     @ width : 绘制四边形的宽度。
     @ height : 绘制四边形的高度。
     
     注意: width = height 绘制的是正方形
     */
    context.addRect(CGRect.init(x: 60, y: 20, width: 160, height: 160))
    // 必和路径
    context.strokePath()
}
效果图如下:
E3722BA7-B7CA-4C5D-BD6C-BF42BE4DB786.png
46E8A830-2248-4F21-A539-DB2FB02C4E0B.png

4、绘制多点之间的连线

// MAKR: 绘制多点之间的连线
func drawLines(rect: CGRect,context:CGContext) -> Void {
    // 设置绘制的颜色
    UIColor.red.set()
    // 设置宽度
    context.setLineWidth(5)
    /**
     绘制各点之间的线段
     
     @ between : 存放的点的数组。
     */
    context.addLines(between: [CGPoint.init(x: 10, y: 50),CGPoint.init(x: 20, y: 30),CGPoint.init(x: 100, y: 150),CGPoint.init(x: 200, y: 20),CGPoint.init(x: 250, y: 70)])
    // 必和路径
    context.strokePath()
}
效果图如下:
B15F9520-C2CE-4A94-88FB-B8747911ED39.png

5、绘制圆弧

// MARK: 绘制圆弧
func drawArc(rect: CGRect,context:CGContext) -> Void {
    // 设置绘制的颜色
    UIColor.red.set()
    // 设置宽度
    context.setLineWidth(5)
    /**
     绘制圆弧
     
     @center : 圆弧的中心点。
     @radius : 圆弧的半径。
     @startAngle : 圆弧开始的角度。
     @endAngle : 圆弧结束的角度。
     @clockwise: 绘制圆弧的方向。true为顺时针,false为逆时针。
     
     // 例子
     context.addArc(center: CGPoint.init(x: rect.size.width * 0.5, y: rect.size.height * 0.5), radius: 80, startAngle: 0, endAngle: .pi * 2, clockwise: true)
     */
    // 移动起始点
    context.move(to: CGPoint.init(x: 100, y: 19))
    /**
     有两个切点和半径绘制圆弧
     
     @tangent1End : 切点一。
     @tangent2End : 切点二。
     @radius : 圆弧的半径。
     */
    context.addArc(tangent1End: CGPoint.init(x: 100, y: 200), tangent2End: CGPoint.init(x: 200, y: 100), radius: 80)
    // 闭合路径
    context.strokePath()
}
效果图如下:
7DF988D6-4C69-4BD6-A849-44678DB42DF0.png
BF7AABAD-503E-4E2D-8859-37223F7EDFE3.png

6、路径绘制的填充

// MARK: 路径绘制的填充
func drawFillPath(rect: CGRect,context:CGContext) -> Void {
    // 设置绘制的颜色
    UIColor.red.set()
    // 设置宽度
    context.setLineWidth(5)
    // 绘制四边形
    context.addRect(CGRect.init(x: 50, y: 50, width: 150, height: 100))
    /**
     填充路径
     
     CGPathFillRule 的参数有两个:
     
     @.evenOdd
     @.winding
     */
    context.fillPath(using: .winding)
    context.strokePath()
}

7、裁剪绘制区域为可绘制的区域

// MARK: 裁剪绘制区域为可绘制的区域
func drawClip(rect: CGRect,context:CGContext) -> Void {
    // 设置绘制的颜色
    UIColor.red.set()
    // 设置宽度
    context.setLineWidth(5)
    // 设置裁剪后可绘制的区域
    context.clip(to: CGRect.init(x: 40, y: 40, width: 60, height: 60))
    /**
     裁剪绘制的图形
     
     1、裁剪所有的区域为可绘制区域。
     context.clip()
     
     2、多区域裁剪
     context.clip(to: [CGRect.init(x: 40, y: 40, width: 30, height: 30),CGRect.init(x: 100, y: 40, width: 100, height: 100),CGRect.init(x: 40, y: 120, width: 40, height: 40)])
     
     3、单区域裁剪
     context.clip(to: CGRect.init(x: 40, y: 40, width: 60, height: 60))

     */
    context.addRect(CGRect.init(x: 50, y: 50, width: 150, height: 100))
    context.strokePath()
}
效果如下:
57E01384-8C93-4103-A1B7-8B0BE0DEB06F.png
B94F12EB-3158-44B0-8F3F-8EC18B565105.png

8、设置填充区域

// MARK: 设置填充区域
func drawFill(rect: CGRect,context:CGContext) -> Void {
    // 设置绘制的颜色
    UIColor.red.set()
    // 设置宽度
    context.setLineWidth(5)
    // 绘制四边形
    context.addRect(CGRect.init(x: 50, y: 50, width: 150, height: 100))
    /**
     区域填充
     
     1、指定单区域的填充
     context.fill(CGRect.init(x: 40, y: 40, width: 30, height: 30))

     2、多区域的填充
     context.fill([CGRect.init(x: 40, y: 40, width: 30, height: 30),CGRect.init(x: 100, y: 40, width: 100, height: 100),CGRect.init(x: 40, y: 120, width: 40, height: 40)])

     */
    context.fill([CGRect.init(x: 40, y: 40, width: 30, height: 30),CGRect.init(x: 100, y: 40, width: 100, height: 100),CGRect.init(x: 40, y: 120, width: 40, height: 40)])
    // 闭合路径绘制图形
    context.strokePath()
}
效果如图:
EF159CD3-D8B9-43E4-A8E1-08356FF144A9.png

9、绘制两点之间的连线

// MARK:绘制两点之间的连线
func drawStrokeLineSegments(rect: CGRect,context:CGContext) -> Void {
    // 设置绘制的颜色
    UIColor.red.set()
    // 设置宽度
    context.setLineWidth(5)

    /**
     绘制两点之间的线段
     
     @between: 是要绘制点的数组集合。
     注意: 如果 between 里面的点的个数是偶数,那就是每两点之间的连线。如果为奇数,在最后一个点将和(0,0)点组成一组的连线。
     */
    context.strokeLineSegments(between: [CGPoint.init(x: 10, y: 20),CGPoint.init(x: 20, y: 70),CGPoint.init(x: 100, y: 120),CGPoint.init(x: 220, y: 70)])
    // 闭合路径
    context.strokePath()
}
效果如下图所示:
0DB5D06E-033B-42B8-9B9E-DCC5D477E3FE.png

10、图像的绘制

// MARK:图像的绘制
func drawImage(rect: CGRect,context:CGContext) -> Void {
    // 设置绘制的颜色
    UIColor.red.set()
    // 设置宽度
    context.setLineWidth(5)
    /**
     图像的绘制
     
     @image : 是要绘制的图像是一个CGImage对象。
     @in : 绘制图像的大小区域。
     
     注意:图像绘制出来是倒立的。
     */
    context.draw((UIImage.init(named: "2.jpg")?.cgImage!)!, in:CGRect.init(x: 50, y: 10, width: 200, height: 180))
    // 闭合路径的绘制
    context.strokePath()
}
效果如下图所示
ED199368-ED32-4AE2-8A00-4CF827A34295.png

11、 绘制椭圆

// MARK: 绘制椭圆
func drawEllipse(rect: CGRect,context:CGContext) {
    // 设置绘制的颜色
    UIColor.red.set()
    // 设置宽度
    context.setLineWidth(5)
    context.addEllipse(in: rect)
    context.strokePath()
}
效果如下图:
00485C5F-1252-48CE-9AD5-F2C7398990DE.png

CGContext的一些其他知识点

// MARK: CGContext 的一些参数的介绍
func introduceContext(context:CGContext) -> Void {
    // 获取typeID
    let typeID = CGContext.typeID
    print(typeID)
    // 存储上下文,便于恢复
    context.saveGState()
    // 恢复上下文
    context.restoreGState()
    // 绘制路径的缩放比例
    context.scaleBy(x: 1, y: 1)
    // 绘制图形的旋转 。by 的取值范围是 -1.0~1.0
    context.rotate(by: 1)
    // 获取当前旋转对象
    let ctm = context.ctm
    print(ctm)
    // 更改上当前的旋转对象数据
    context.concatenate(CGAffineTransform.init(rotationAngle: 0.5))
    // 再获取当前旋转对象
    let ctm1 = context.ctm
    print(ctm1)
    // 设置绘制路径的线宽
    context.setLineWidth(6)
    /**
     设置线的头部形状
     
     可选的参数
     @ butt  和 square 基本一样,属于粗狂的端头。(矩形)
     @ round 半圆形的线头
     @ square
     */
    context.setLineCap(.butt)
    /**
     设置绘制路径拐角处的形状
     
     可以选择的参数
     @ miter  切角形
     @ round  圆角形
     @ bevel  斜切角形
     */
    context.setLineJoin(.bevel)
    // 设置切角的大小
    context.setMiterLimit(3)
    // 清楚所有绘制的路径图形
    context.closePath()
    // 设置绘制图形的透明度
    context.setAlpha(0.6)
    // 开启新的路径,丢弃老的路径
    context.beginPath()
    // 绘制路径的替换,用于剪切图形
    context.replacePathWithStrokedPath()
    /**
     判断给定的点是否在绘制图形上
     
     @point: 给定的点
     @mode: 判断点的规则
     
     CGPathDrawingMode 路径绘制的模型
     @ fill :表示用非零绕数规则。
     @ eoFill: 表示用奇偶规则
     @ stroke :表示填充。
     @ fillStroke :表示描线,填充。
     @ eoFillStroke :表示描线,不是填充。
     */
    let isSave = context.pathContains(CGPoint.init(x: 101, y: 52), mode: .stroke)
    print(isSave)
    // 绘制四边形
    context.addRect(CGRect.init(x: 100, y: 50, width: 150, height: 100))
    // 切除某一区域绘制的图形
    context.clear(CGRect.init(x: 120, y: 50, width: 50, height: 30))
    // 设置画笔的颜色
    UIColor.red.set()
    context.setFillColor(UIColor.red.cgColor)
    // 闭合路径
    context.strokePath()
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容