IOS中贝塞尔曲线的使用
贝塞尔曲线是一种很好用的绘图方式,这种曲线借助中间点和控制点生成平滑曲线,在工业设计方面有很多应用,而在IOS开发过程中,也内置了这个模块,使得开发者能够使用它,进行相关的复杂曲线绘制
在IOS中,使用贝塞尔曲线,需要使用UIBezierPath,通过设置途径点+控制点或者通过构造函数可以制作多种线条和形状,不妨将它们统称为:路径,路径往往不会单独使用,一般都是结合CAShapeLayer,绘图操作一般在draw方法中进行
下面开始第一次伟大的尝试:画一条线,这个比较简单,设置起点和终点即可
//要搭配layer
let lineLayer = CAShapeLayer();
//贝塞尔曲线
var bezierLine : UIBezierPath?;
override func draw(_ rect: CGRect) {
bezierLine = UIBezierPath();
//设置起点
bezierLine?.move(to: CGPoint.init(x: 110, y: 200));
//设置终点
bezierLine?.addLine(to: CGPoint.init(x: 160, y: 300));
lineLayer.path = bezierLine?.cgPath;
lineLayer.fillColor = UIColor.clear.cgColor;
lineLayer.lineWidth = 3;
lineLayer.strokeColor = UIColor.black.cgColor;
self.layer.addSublayer(lineLayer);
}
从这个思路来看的话,我们可以通过设置的中间点,来实现更加复杂的图形,例如我们可以通过设置三个点的位置,来绘制一个简单的三角形
override func draw(_ rect: CGRect) {
//通过设置中间点,形成一个三角形
bezierLine = UIBezierPath();
bezierLine?.move(to: CGPoint.init(x: 120, y: 120));
bezierLine?.addLine(to: CGPoint.init(x: 190, y: 190));
bezierLine?.addLine(to: CGPoint.init(x: 220, y: 150));
//bezierLine?.addLine(to: CGPoint.init(x: 20, y: 20)); //可以通过手动设置终点的形式制作封闭图形
bezierLine?.close(); //亦可直接关闭图形,系统会自动将起点加入到最后,构成封闭图形
lineLayer.path = bezierLine?.cgPath;
lineLayer.fillColor = UIColor.clear.cgColor;
lineLayer.lineWidth = 3;
lineLayer.strokeColor = UIColor.black.cgColor;
self.layer.addSublayer(lineLayer);
}
事实上我们需要更多的了解,才能对CAShapeLayer产生比较清晰的认识,CAShapeLayer继承自CALayer,因此,可使用CALayer的所有属性。但是,CAShapeLayer需要和贝塞尔曲线配合使用才有意义。
也就是说我们可以设置其中的属性,来实现线条的颜色改变,实线虚线等多种效果,CAShapeLayer其中的Shape就是指的是形状,也就是说,他需要一个形状才能完成渲染,而UIBezierPath就是能够通过代码来设置特定的形状,UIBezierPath+CAShapeLayer就可以完成相关的渲染。
事实上UIBezierPath提供了一些构造函数,使得我们可以通过构造函数直接生成一些常用图形:矩形、椭圆等
//生成指定尺寸的矩形,尺寸合适也可以生成正方形
UIBezierPath.init(rect: CGRect.init(x: 10, y: 10, width: 160, height: 80));
//理论上形成的是指定CGRect的内切椭圆,如果CGRect是一个正方形,生成的就是圆形
UIBezierPath.init(ovalIn: CGRect.init(x: 10, y: 10, width: 150, height: 100));
//圆角矩形的绘制
UIBezierPath.init(roundedRect: CGRect.init(x: 10, y: 10, width: 100, height: 100), cornerRadius: 25);
//圆弧的绘制
/*
* 参数的描述:arcCenter:圆弧的圆心的位置
* radius:圆弧所在圆的半径 startAngle:起始点的角度 endAngle:终点的角度
* clockwise:是否沿顺时针方向
* 对于转动角度而言,使用Pi来表示角度,一个整圆的角度是2*pi,可以按照需要自行设置
*/
UIBezierPath.init(arcCenter: CGPoint.init(x: 100, y: 100), radius: 50, startAngle: 0, endAngle: CGFloat.pi, clockwise: true);
除此之外,我们绘制的图形都是规则的图形,但是贝塞尔曲线的拿手好戏是进行平滑曲线的绘制,下面进行简单的介绍
贝塞尔曲线二次曲线
先看一下官方的回答
简单来说就是:所谓二次曲线,存在一个起始点:startPoint,一个终点:endPoint,可以形成一条直线,在此基础上,再加上一个控制点:controlPoint,最终形成的曲线由起点出发,趋向于控制点(不会到达),最终到达终点
用代码实现的话,就是这样的
override func draw(_ rect: CGRect) {
//二次曲线
bezierLine = UIBezierPath();
bezierLine?.move(to: CGPoint.init(x: 110, y: 200))
bezierLine?.addQuadCurve(to: CGPoint.init(x: 210, y: 230), controlPoint: CGPoint.init(x: 155, y: 160));
lineLayer.path = bezierLine?.cgPath;
lineLayer.fillColor = UIColor.clear.cgColor;
lineLayer.lineWidth = 3;
lineLayer.strokeColor = UIColor.black.cgColor;
self.layer.addSublayer(lineLayer);
}
贝塞尔曲线三次曲线
再来看一下官方回答
实际上,可以理解为:所谓三次曲线就是在二次曲线的基础上,再加上一个控制点2: controlPoint1,最终形成的曲线,由起点出发,先趋向于第一个控制点(不会到达),再趋向于第二个控制点(不会到达),最后到达终点,形成一个曲线
用代码来实现的话就是
override func draw(_ rect: CGRect) {
//三次次曲线
bezierLine = UIBezierPath();
bezierLine?.move(to: CGPoint.init(x: 110, y: 200))
//bezierLine?.addQuadCurve(to: CGPoint.init(x: 210, y: 230), controlPoint: CGPoint.init(x: 155, y: 160));
bezierLine?.addCurve(to: CGPoint.init(x: 360, y: 230), controlPoint1: CGPoint.init(x: 190, y: 150), controlPoint2: CGPoint.init(x: 280, y: 280))
lineLayer.path = bezierLine?.cgPath;
lineLayer.fillColor = UIColor.clear.cgColor;
lineLayer.lineWidth = 3;
lineLayer.strokeColor = UIColor.black.cgColor;
self.layer.addSublayer(lineLayer);
}
以上就是基本操作了,真正使用的话,需要针对场景做出调整,下面是几个参考的链接
基本使用:传送门
高次贝塞尔曲线介绍:传送门