前面已经讲解了Quartz 2D的原理, 那么下面就来利用Quart 2D来画一些最基本的图形;
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()
}
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()
}
说到这里,用两幅图区分一下setLineCap和setLineJoin这两个方法:
3.曲线
Quartz 使用计算机图形学中的多项式来绘制曲线,支持二次和三次曲线;
利用move(to: beginPoint)来设定曲线起点
利用addQuadCurve(to: endPoint, control: controlPoint)来绘制二次曲线
利用addCurve(to: endPoint, control1:control1Point, control2: control2Point)来绘制三次曲线
注: beginPoint为曲线起点, endPoint为曲线终点, controlPoint为控制曲线的点
具体代码:
// 二次曲线
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()
}
// 三次曲线
// 连续画三条
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()
}
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()
}
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()
}
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()
}
通过上图的效果展示, 总结如下:
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()
}
分析红线部分代码:
// 由上句代码知道 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)