引言:
UIBezierPath类只是CGPathRef数据类型和path绘图属性的一个封装。
参考:
摘要:
1.一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋,我们在绘图工具上看到的钢笔工具就是来做这种矢量曲线的。
2.出现的原因:
由于用计算机画图大部分时间是操作鼠标来掌握线条的路径,与手绘的感觉和效果有很大的差别。即使是一位精明的画师能轻松绘出各种图形,拿到鼠标想随心所欲的画图也不是一件容易的事。这一点是计算机万万不能代替手工的工作,所以到目前为止人们只能颇感无奈。使用贝塞尔工具画图很大程度上弥补了这一缺憾。
贝塞尔曲线是计算机图形图像造型的基本工具,是图形造型运用得最多的基本线条之一。它通过控制曲线上的四个点(起始点、终止点以及两个相互分离的中间点)来创造、编辑图形。
说到底,就是直接用这个类来画二维图形,也是666
找到一篇很不错的博客
摘要出一部分,有空的话,看看全文比较好
ps:发现该作者的其它博客也很不错,有空看看
1、CAShapeLayer继承自CALayer,可以使用CALayer的所有属性值
2、CAShapeLayer需要与贝塞尔曲线配合使用才有意义
3、使用CAShapeLayer与贝塞尔曲线可以实现不在view的drawRect方法中画出有一些想要的图形
4、CAShapeLayer属于CoreAnimation框架,其动画渲染直接提交到手机的GPU当中,相较于view的drawRect方法使用CPU渲染而言,其效率极高,能大大优化内存使用情况。
个人经验:可以重写UIView的子类中的drawRect来实现进度条效果,但是UIView的drawRect是用CPU渲染实现的,而使用CAShapeLayer效率更高,因为它用的是GPU渲染。
创建的步骤:
(1)创建一个Bezier path对象(这没什么好说的)
(2)使用方法moveToPoint:去设置初始线段的起点。这就不得不吐槽了,为什么是moveToPoint呢?这命名让人感觉好像终点的样子,假如改成moveFromPoint多好,能降低误导概率
[_path moveToPoint:CGPointMake(startX, startY)];
(3)添加line或者curve去定义一个或者多个subpaths。
line是直线段,curve是曲线段
//3.1三次贝塞尔曲线举个例子:(三次和二次addQuadCurveToPoint,貌似咋一看最大的区别是能加三个还是两个参数)
//三点曲线--让小方块的下滑线路
[_path addCurveToPoint:CGPointMake(0, 600)/*终点*/ controlPoint1:CGPointMake(startX, startY) /*起点*/controlPoint2:CGPointMake(startX - 180, startY - 200)];/*中途点*/
//3.2直线绘制多边形举个例子:
多边形是一些简单的形状,这些形状是由一些直线线条组成,我们可以用moveToPoint: 和 addLineToPoint:方法去构建
方法moveToPoint:设置我们想要创建形状的起点。从这点开始,我们可以用方法addLineToPoint:去创建一个形状的线段。
我们可以连续的创建line,每一个line的起点都是先前的终点,终点就是指定的点。
下面的代码描述了如何用线段去创建一个五边形。第五条线通过调用closePath方法得到的,它连接了最后一个点(0,40)和第一个点(100,0)
说明:closePath方法不仅结束一个shape的subpath表述,它也在最后一个点和第一个点之间画一条线段,如果我们画多边形的话,这个一个便利的方法我们不需要去画最后一条线
//自定义view里面自定义绘制这个view
- (void)drawRect:(CGRect)rect
{
UIColor *color = [UIColor redColor];
[color set]; //设置线条颜色
UIBezierPath* aPath = [UIBezierPath bezierPath];
aPath.lineWidth = 5.0;
aPath.lineCapStyle = kCGLineCapRound; //线条拐角
aPath.lineJoinStyle = kCGLineCapRound; //终点处理
// Set the starting point of the shape.
[aPath moveToPoint:CGPointMake(100.0, 0.0)];
// Draw the lines
[aPath addLineToPoint:CGPointMake(200.0, 40.0)];
[aPath addLineToPoint:CGPointMake(160, 140)];
[aPath addLineToPoint:CGPointMake(40.0, 140)];
[aPath addLineToPoint:CGPointMake(0.0, 40.0)];
[aPath closePath];//第五条线通过调用closePath方法得到的
[aPath stroke];//Draws line 根据坐标点连线
}
至于绘制矩形(bezierPathWithRect)圆形/椭圆形(bezierPathWithOvalInRect)之类的是系统对常用的一点封装而已。
ps:1.绘图呢,调用drawRect(重绘父view)和CALayer都可以,但是相比之下CALayer调用GPU来进行绘制,性能会更好点。如果要组合成动画,还是要用CALayer,(不过很多时候用它的子类CAShapeLayer)
2.它这种直线段绘图(addLineToPoint)跟代码顺序有关,所以敲的时候要注意了
3.另外如果调起 [aPath stroke],它是会自动连上起点和终点的,当然也可以用填充模式[aPath fill]替代[aPath stroke]画线模式
==
(4)改变UIBezierPath对象跟绘图相关的属性。
例如,我们可以设置stroked path的属性lineWidth和lineJoinStyle。也可以设置filled path的属性usesEvenOddFillRule。
贝塞尔曲线的修改:
1.底层修改(比较麻烦):
虽然通常我们可以用UIBezierPath类的方法去添加直线段和曲线段,UIBezierPath类还提供了一个属性CGPath,我们可以用来直接修改底层的path data type。如果我们希望用Core Graphics 框架函数去创建path,则我们要用到此属性。
>有两种方法可以用来修改和UIBezierPath对象相关的path。可以完全的使用Core Graphics函数去修改path,也可以使用Core Graphics函数和UIBezierPath函数混合去修改。第一种方法在某些方面相对来说比较容易。我们可以创建一个CGPathRef数据类型,并调用我们需要修改path信息的函数。
如果我们使用Core Graphics函数和UIBezierPath函数混合方法,我们必须小心的移动path 信息在两者之间。因为UIBezierPath类拥有自己底层的CGPathRef data type,我们不能简单的检索该类型并直接的修改它。相反,我们应该生成一个副本,然后修改此副本,然后赋值此副本给CGPath属性,如下代码:
UIBezierPath* aPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 300, 300)];
// Get the CGPathRef and create a mutable version.
CGPathRef cgPath = aPath.CGPath;
CGMutablePathRef mutablePath = CGPathCreateMutableCopy(cgPath);
// Modify the path and assign it back to the UIBezierPath object
CGPathAddEllipseInRect(mutablePath, NULL, CGRectMake(50, 50, 200, 200));
aPath.CGPath = mutablePath;
// Release both the mutable copy of the path.
CGPathRelease(mutablePath);
ps:名称解释之GPU
GPU相当于专用于图像处理的CPU,正因为它专,所以它强,在处理图像时它的工作效率远高于CPU,但是CPU是通用的数据处理器,在处理数值计算时是它的强项,它能完成的任务是GPU无法代替的,所以不能用GPU来代替CPU。
时下的GPU多数拥有2D或3D图形加速功能。如果CPU想画一个二维图形,只需要发个指令给GPU,如“在坐标位置(x, y)处画个长和宽为a×b大小的长方形”,GPU就可以迅速计算出该图形的所有像素,并在显示器上指定位置画出相应的图形,画完后就通知CPU “我画完了”,然后等待CPU发出下一条图形指令。
有了GPU,CPU就从图形处理的任务中解放出来,可以执行其他更多的系统任务,这样可以大大提高计算机的整体性能