swift -- Quartz 2D -- 绘制图层:线条, 三角形, 矩形, 圆, 弧, 扇形, 虚线等

前面已经讲解了Quartz 2D的原理, 那么下面就来利用Quart 2D来画一些最基本的图形;

步骤

  • 获取图形上下文
  • 创建路径(描述路径)
  • 绘制图形
  • 把路径添加到上下文
  • 利用图形上下文将绘制的所有内容渲染显示到view上面

获取图形上下文

  • 新建一个类,继承自UIView
  • 实现- (void)drawRect:(CGRect)rect方法,然后在这个方法中进行获取上下文的操作步骤
    注意:
    - 只有在在drawRect:方法中才能取得跟view相关联的图形上下文
    - drawRect:方法在view第一次显示到屏幕上时调用
    - 或者手动调用view的setNeedsDisplay或者setNeedsDisplayInRect:时会调用drawRect:方法
    - 注意手动 [self drawRect] 是无效的写法

画线条

1.直线
方法一:

 override func draw(_ rect: CGRect) {
        // 获取当前的图形上下文
        let context = UIGraphicsGetCurrentContext()

        // 设置线条的属性
        // 1.设置线宽
        context?.setLineWidth(20)
        // 2.设置线条的颜色
        context?.setStrokeColor(UIColor.brown.cgColor)
        /**
         *miter,切角
         *round,圆角
         *bevel
         */
        // 3.设置顶角样式
        context?.setLineCap(.round)
        // 创建路径
        let path = CGMutablePath()
        // 给路径设置起点(开始画线,需要将起点移动到指定的point)
        path.move(to: CGPoint(x: 20, y: 200))
        // 添加一根线到另一个点 (两点一线)
        path.addLine(to: CGPoint(x: 200, y: 200))
        // 将路径添加到上下文
        context?.addPath(path)
        // 渲染图形到上下文
        context?.strokePath()
  }

方法二:

override func draw(_ rect: CGRect) {
       // 获取当前的图形上下文
        let context = UIGraphicsGetCurrentContext()

        // 设置线条的属性
        // 1.设置线宽
        context?.setLineWidth(20)
        // 2.设置线条的颜色
        context?.setStrokeColor(UIColor.brown.cgColor)

        // 开始画线,需要将起点移动到指定的point
        context?.move(to: CGPoint(x: 20, y: 200))
        // 添加一根线到另一个点 (两点一线)
        context?.addLine(to: CGPoint(x: 200, y: 200))
        // 渲染图形到上下文
        context?.strokePath()
  }

方法三:

override func draw(_ rect: CGRect) {
//UIKIT 封装的绘图功能  贝斯曲线
// 获取贝塞尔路径
        let path = UIBezierPath()
        // 设置起点
        path.move(to: CGPoint(x: 20, y: 200))
        // 添加一根线到终点
        path.addLine(to: CGPoint(x: 200, y: 200))
        // 绘制路径
        path.stroke()
}

线宽20 线顶角为round 如下图
swift -- Quartz 2D -- 绘制图层:线条, 三角形, 矩形, 圆, 弧, 扇形, 虚线等_第1张图片

2.折线

override func draw(_ rect: CGRect) {
        // 获取当前的图形上下文
        let context = UIGraphicsGetCurrentContext()

        // 设置线条的属性
        // 1.设置线宽
        context?.setLineWidth(20)
        // 2.设置线条的颜色
        context?.setStrokeColor(UIColor.brown.cgColor)
        // 开始画线,需要将起点移动到指定的point
        context?.move(to: CGPoint(x: 20, y: 200))
        // 添加一根线到另一个点 (两点一线)
        context?.addLine(to: CGPoint(x: 200, y: 200))
        context?.addLine(to: CGPoint(x: 200, y: 380))
        // 渲染图形到上下文
        context?.strokePath()
}

线宽20 顶角为round 如下图
swift -- Quartz 2D -- 绘制图层:线条, 三角形, 矩形, 圆, 弧, 扇形, 虚线等_第2张图片

说到这里,用两幅图区分一下setLineCap和setLineJoin这两个方法:
swift -- Quartz 2D -- 绘制图层:线条, 三角形, 矩形, 圆, 弧, 扇形, 虚线等_第3张图片swift -- Quartz 2D -- 绘制图层:线条, 三角形, 矩形, 圆, 弧, 扇形, 虚线等_第4张图片

3.曲线
Quartz 使用计算机图形学中的多项式来绘制曲线,支持二次和三次曲线;

利用move(to: beginPoint)来设定曲线起点
利用addQuadCurve(to: endPoint, control: controlPoint)来绘制二次曲线
利用addCurve(to: endPoint, control1:control1Point, control2: control2Point)来绘制三次曲线
注: beginPoint为曲线起点, endPoint为曲线终点, controlPoint为控制曲线的点

原理图入下图所示
swift -- Quartz 2D -- 绘制图层:线条, 三角形, 矩形, 圆, 弧, 扇形, 虚线等_第5张图片
swift -- Quartz 2D -- 绘制图层:线条, 三角形, 矩形, 圆, 弧, 扇形, 虚线等_第6张图片

具体代码:

// 二次曲线
override func draw(_ rect: CGRect) {
        // 获取当前的图形上下文
        let context = UIGraphicsGetCurrentContext()

        context?.move(to: CGPoint(x: 100, y: 0))
        context?.addQuadCurve(to: CGPoint(x: 300, y: 0), control:CGPoint(x: 200, y: 100))
context?.strokePath()
    }

模拟器效果:
swift -- Quartz 2D -- 绘制图层:线条, 三角形, 矩形, 圆, 弧, 扇形, 虚线等_第7张图片

// 三次曲线
// 连续画三条
override func draw(_ rect: CGRect) {
        // 获取当前的图形上下文
        let context = UIGraphicsGetCurrentContext()
        context?.move(to: CGPoint(x: 10, y: 100))
        context?.addCurve(to: CGPoint(x: 50, y: 100), control1: CGPoint(x: 20, y: 50), control2: CGPoint(x: 40, y: 150))
        // 接上一个终点开始画线
        context?.move(to: CGPoint(x: 50, y: 100))
        context?.addCurve(to: CGPoint(x: 90, y: 100), control1: CGPoint(x: 60, y: 50), control2: CGPoint(x: 80, y: 150))
        // 接上一个终点开始画线
        context?.move(to: CGPoint(x: 90, y: 100))
        context?.addCurve(to: CGPoint(x: 130, y: 100), control1: CGPoint(x: 100, y: 50), control2: CGPoint(x: 120, y: 150))
        context?.strokePath()
   }

模拟器效果:
swift -- Quartz 2D -- 绘制图层:线条, 三角形, 矩形, 圆, 弧, 扇形, 虚线等_第8张图片

4.三角形
只要三个点就行跟画一条线方式一样,把三点连接起来
代码如下:

override func draw(_ rect: CGRect) {
        // 获取当前的图形上下文
        let context = UIGraphicsGetCurrentContext()
        // 设置边框颜色
        context?.setStrokeColor(UIColor.green.cgColor)
        // 设置填充颜色
        context?.setFillColor(UIColor.brown.cgColor)
        // 开始画线,需要将起点移动到指定的point
        context?.move(to: CGPoint(x: 20, y: 200))
        // 添加一根线到另一个点 (两点一线)
        context?.addLine(to: CGPoint(x: 200, y: 200))
        // 添加一根线到另一个点 (两点一线)
        context?.addLine(to: CGPoint(x: 200, y: 100))

        // 画线完毕,最后将起点和终点封起来
        context?.closePath()
        /*
            stroke      : 边框;
            fill        : 填充
            fillStroke  : 边框 + 填充
         */
        context?.drawPath(using: .fillStroke)
        // 渲染上下文
        context?.strokePath()
    }

模拟器效果:
swift -- Quartz 2D -- 绘制图层:线条, 三角形, 矩形, 圆, 弧, 扇形, 虚线等_第9张图片

5.四边形
和三角形的原理一样 确定四个点连线
代码如下:

override func draw(_ rect: CGRect) {
        // 获取当前的图形上下文
        let context = UIGraphicsGetCurrentContext()

        // 开始画线,需要将起点移动到指定的point
        context?.move(to: CGPoint(x: 20, y: 200))
        // 添加一根线到另一个点 (两点一线)
        context?.addLine(to: CGPoint(x: 200, y: 200))
        // 添加一根线到另一个点 (两点一线)
        context?.addLine(to: CGPoint(x: 200, y: 100))
        // 添加一根线到另一个点 (两点一线)
        context?.addLine(to: CGPoint(x: 20, y: 100))

        // 画线完毕,最后将起点和终点封起来
        context?.closePath()

        // 渲染上下文
        context?.strokePath()
    }

模拟器效果:
swift -- Quartz 2D -- 绘制图层:线条, 三角形, 矩形, 圆, 弧, 扇形, 虚线等_第10张图片

6.弧,扇形,圆
在swift里面,有两个画圆弧的方法:

/*
 ** 这个方法是根据圆点和半径来确定圆的位置和大小,根据Angle来确定圆弧的起点和终点
 ** center: 圆点
 ** radius: 半径
 ** startAngle: 开始的弧度
 ** endAngle: 结束的弧度
 ** clockwise: 0为顺时针,1为逆时针
 */
context?.addArc(center: center, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: clockwise)
/*
 ** 这个方法通过两个切点和半径,来确定一段圆弧
 ** tangent1End: 圆弧的第一个切点
 ** tangent2End: 圆弧的第二个切点
 ** radius: 圆弧的半径
 */
context?.addArc(tangent1End: tangent1End, tangent2End: tangent2End, radius: radius)

注: 圆弧绕一周,其实就是一个圆, 而扇形是圆弧的两个端点和圆点的连线,形成一个封闭的图形
在swift中,可以用上述两种方法,分别画出圆,圆弧以及扇形
* 方法一:*
代码如下:

override func draw(_ rect: CGRect) {
        // 获取当前的图形上下文
        let context = UIGraphicsGetCurrentContext()
// 画圆
        context?.addArc(center: CGPoint(x: 100, y: 100), radius: 50, startAngle: CGFloat( -30 / 180.0 * Double.pi), endAngle: CGFloat( 330.0 / 180.0 * Double.pi), clockwise: false)
        context?.move(to: CGPoint(x: 150, y: 100))

        // 扇形
        context?.move(to: CGPoint(x: 100, y: 200))
        context?.addArc(center: CGPoint(x: 100, y: 200), radius: 50, startAngle: CGFloat( 30 / 180.0 * Double.pi), endAngle: CGFloat( 330.0 / 180.0 * Double.pi), clockwise: true)
        context?.addLine(to: CGPoint(x: 100, y: 200))

        // 第二个圆
        context?.addArc(center: CGPoint(x: 100, y: 300), radius: 50, startAngle: CGFloat( 0 / 180.0 * Double.pi), endAngle: CGFloat( 360 / 180.0 * Double.pi), clockwise: false)

        // 第三个圆
        context?.move(to: CGPoint(x: 150, y: 400))
        context?.addArc(center: CGPoint(x: 100, y: 400), radius: 50, startAngle: CGFloat( 0 / 180.0 * Double.pi), endAngle: CGFloat( 360 / 180.0 * Double.pi), clockwise: false)

        // 第一个圆弧
        context?.move(to: CGPoint(x: 150, y: 500))
        context?.addArc(center: CGPoint(x: 100, y: 500), radius: 50, startAngle: CGFloat( 0 / 180.0 * Double.pi), endAngle: CGFloat( 45 / 180.0 * Double.pi), clockwise: true)
        // 第二个圆弧
        context?.move(to: CGPoint(x: 150, y: 600))
        context?.addArc(center: CGPoint(x: 100, y: 600), radius: 50, startAngle: CGFloat( 0 / 180.0 * Double.pi), endAngle: CGFloat( 45 / 180.0 * Double.pi), clockwise: false)
        context?.strokePath()
}

虚拟机效果图
swift -- Quartz 2D -- 绘制图层:线条, 三角形, 矩形, 圆, 弧, 扇形, 虚线等_第11张图片

通过上图的效果展示, 总结如下:
1.当startAngle为0,即标准的起始点在3点钟的位置;
2.在同一块context上画两个圆的时候,当第一个圆画完之后,要将point转移到下一个圆的起始点(根据startAngle的不同,以及圆点和半径的位置计算出来)
3.画圆的轨迹要根据clockwise来决定,false表示顺时针,true表示逆时针
4.startAngle/endAngle的弧度大小,是顺时针方向的

* 方法二:*
代码如下:

override func draw(_ rect: CGRect) {
        // 获取当前的图形上下文
        let context = UIGraphicsGetCurrentContext()
        // 画正方形带弧度
        context?.move(to: CGPoint(x: 110, y: 100))
        context?.addArc(tangent1End: CGPoint(x: 200, y: 100), tangent2End: CGPoint(x: 200, y: 200), radius: 10.0)
        context?.addArc(tangent1End: CGPoint(x: 200, y: 200), tangent2End: CGPoint(x: 100, y: 200), radius: 10.0)
        context?.addArc(tangent1End: CGPoint(x: 100, y: 200), tangent2End: CGPoint(x: 100, y: 100), radius: 10.0)
        context?.addArc(tangent1End: CGPoint(x: 100, y: 100), tangent2End: CGPoint(x: 200, y: 100), radius: 10.0)
        // 画圆
        context?.move(to: CGPoint(x: 200, y: 300))
        context?.addArc(tangent1End: CGPoint(x: 300, y: 300), tangent2End: CGPoint(x: 300, y: 400), radius: 100)
        context?.addArc(tangent1End: CGPoint(x: 300, y: 500), tangent2End: CGPoint(x: 200, y: 500), radius: 100)
        context?.addArc(tangent1End: CGPoint(x: 100, y: 500), tangent2End: CGPoint(x: 100, y: 400), radius: 100)
        context?.addArc(tangent1End: CGPoint(x: 100, y: 300), tangent2End: CGPoint(x: 200, y: 300), radius: 100)
        context?.strokePath()
        // 画虚线
        context?.move(to: CGPoint(x: 100, y: 300))
        context?.setLineDash(phase: 0, lengths: [5,10])
        context?.addLine(to: CGPoint(x: 300, y: 300))
        context?.addLine(to: CGPoint(x: 300, y: 500))
        context?.addLine(to: CGPoint(x: 100, y: 500))
        context?.addLine(to: CGPoint(x: 100, y: 300))
        context?.strokePath()
    }

效果图:
swift -- Quartz 2D -- 绘制图层:线条, 三角形, 矩形, 圆, 弧, 扇形, 虚线等_第12张图片

分析红线部分代码:

// 由上句代码知道  point已经走到CGPoint(x: 100, y: 400) 这个点, 那么下面这句代码之后, 确定了切线一和切线二, 切线一就是(100,400)和(100,300)两点的连线, 切线二是(100,300)和(200,300)的连线,半径为100,我们可以分析出,圆点在(200,400),圆弧就如图所示
context?.addArc(tangent1End: CGPoint(x: 100, y: 300), tangent2End: CGPoint(x: 200, y: 300), radius: 100)

Quartz 2D的强大毋庸置疑,我在这里也只是做了一些简单的应用,也是本人通过效果图的展示结果做出的一些理解,可能会存在一些错误, 还请大家多多指点

你可能感兴趣的:(quartz)