之前一篇我们主要了解实践了canvas的drawXXX方法,都是绘制一些很规矩的图形,例如圆形、矩形、直线、画点、画椭圆、绘制圆角矩形、绘制扇形、绘制弧线这些,大家也肯定发现了这些都是规规矩矩图形,那么如果要画一条折线,画一个三角形之类的自定义图形,该怎么办呢?这时候就改path出场了,对于canvas就是drawPath了。
那么path是什么呢?听听Android怎么说:“The Path class encapsulates compound (multiple contour) geometric paths consisting of straight line segments, quadratic curves, and cubic curves. It can be drawn with canvas.drawPath(path, paint), either filled or stroked (based on the paint's Style), or it can be used for clipping or to draw text on a path.”大概翻一下大概是:Path类包含了由直线、二次曲线、三次曲线组成多种符合的集合路径图形,它可以用canvas.drawPath()来绘制,并且可以使填充的或者描边的(是基于paint的style的),并且它可以用于裁剪或者在一条path上面绘制文本。
Path类的方法主要是addXXX和XXXTo方法:
addCircle(float x, float y, float radius, Direction dir):参数跟上一篇的drawCircle很类似,不过多了一个Direction参数,他的意思就是“The direction to wind the circle's contour”就是圆形绘制的方向,参数值有Path.Direction.CW和Path.Direction.CCW两种,前者是代表顺时针绘制,后者则是逆时针绘制。
除了addCircle之外还有addOval、addRect、addRoundRect这样的,但是无一例外跟canvas直接draw的相比都多了一个Direction参数,就是指绘制方向的,在绘制单个图形时候我们这个参数设置成逆时针与顺时针都没什么影响,在图形组合时候会有影响,后面再说。
lineTo(float x, float y):画直线,意思就是“Add a line from the last point to the specified point (x,y). If no moveTo() call has been made for this contour, the first point is automatically set to (0,0).”从上面点添加一条到特定点(x,y)的直线,如果moveTo方法没有被path调用,那么第一个点就自从从(0,0)开始。跟canvas的drawLine方法相比它只有一个坐标,因为它总是从上个绘制点往指定点绘制的,而不是像drawLine那样子需要两个坐标来确定一条直线,所以lineTo方法为一次性绘制多条连续的直线提供了方便。
rLineTo(float dx, float dy):也是画直线,这算是lineTo的兄弟了,也是只有一对参数,确定一个坐标,但是它与lineTo的区别是,它的坐标的确定是依据于上个坐标点的坐标值的,也就是相对于上个坐标值的,不是一个绝对值,说起来比较抽象,我们来看一个例子,按照如下路径来绘制一条直线:(200, 200)→(250, 500)就是从200,200那个到250,500画一条直线,这些也都是相对于坐标系的绝对坐标,那么如果用rLineTo如何写呢?就这么写(200, 200)→(50, 300),发现了吧?就是在原来的坐标值累加或者减,就是rLineTo它的参数是相对值,是相对于上一个点要偏移的量,它不是一个绝对值,而lineTo就是一个绝对坐标。
moveTo(float x, float y):“Set the beginning of the next contour to the point (x,y).”设置下一个path绘制的起点,其实也很好理解,默认绘制起点是坐标原点,但是不想从那里开始绘制怎么办?就可以调用这个方法,或者在绘制的过程中,突然不想从上一个点接着绘制了,想要从一个新的点开始绘制,调用这个方法也是 可以的。
rMoveTo(float dx, float dy):它跟moveTo的关系就如同rLineTo和lineTo的关系了,所以意思就类比上面的就好了
arcTo(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean forceMoveTo) :画弧形,这个跟canvas的drawArc相比少了一个userCenter参数,上篇我们说过该参数如果userCenter为true是绘制扇形,false是绘制圆弧,而现在该函数没有userCenter是因为该函数默认userCenter为false了,因为该函数只用来画圆弧,不画扇形,但是可以看到又多了一个forceMoveTo函数,它的意思是“If true, always begin a new contour with the arc”如果是true那么在话弧度时候就开始一个新的轮廓,啥意思呢?这么解释吧:好比我们刚绘制了一条直线,然后想绘制一段圆弧,那么这个圆弧跟刚刚的直线的末端是否要相连呢?这个时候就是用这个forceMoveTo来控制的了,如果为true,那么直线末端就不跟圆弧开始出相连,否则就是相连了
addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle):这个也是画圆弧的,那么跟上面的arcTo有什么区别呢?区别就在于它直接设了上面的 arcTo的forceMoveTo参数为true了,所以用它绘制圆弧,就不跟path前面绘制的图形有任何联系
close():代表关闭了path绘制,啥意思呢?“Close the current contour. If the current point is not equal to the first point of the contour, a line segment is automatically added.”关闭当前的path绘制,如果当前结束点不是path开始绘制的七点,那么就会在起点和终点支架连接一条线段。举个例子,我们相用path绘制一个三角形,那咱么只需要绘制两条边就好了,然后调用close,那么第三条边就自动绘制上去了,但是有些情况比较特殊,不调用close方法图形也能闭环,好比我们paint设置style是填充模式,还是说绘制三角形,当绘制了两条边时候,两条边之间就已经被颜色填充了,所以就直接出现了三角形了,也自然不需要close来连接起点和终点构成三角形了
setFillType(FillType ft):path的填充模式,这有个前提就是画笔要设置成是填充模式,它主要是用来设置图形相交时候的填充模式算法的,主要是四种模式,但是我们只说两种模式,因为后两种跟前两种是相反的,第一种EVEN_ODD奇偶原则,“对于平面中的任意一点,向任意方向射出一条射线(是射线不是直线哦,是有起点的,只是向一个方向无限延伸),这条射线和图形的相交次数(必须相交,不是相切)是奇数,则认为这个点在图形的内部,是需要涂色的区域,如果是偶数则认为不在此区域,那么是不需要涂色的区域”,然后是第二种WINDING非零环绕原则:“它需要你图形中的所有线条都是有方向的,然后同样的是在平面中的任意一点向任意方向发射出一条射线,但是规则不一样,以0为初始值,对于射线和图形的所有交点,遇到每个顺时针的交点(图形从射线的左边向右穿过)把结果加1,遇到每个逆时针的交点(图形从射线的右边向左穿过)把结果减1,最终把所有的交点都算上,得到的结果如果不是0,那么认为此点在图形内部,是需要被涂色的区域,如果是0,那么此点在图形外部,是不需要涂色的区域”,这里面用到了线条的方向,所以上面咱们说的Path.Direction就用上了。