Path
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(Path path)函数绘制,使用Paint.Style填充或描边,或它可以用于裁剪canvas.clipPath()或绘制文本路径canvas.drawTextOnPath()
根据android doc中的介绍我们可以看到,path是用来描述绘制几何图形路径的.其中包括我们经常见到的圆,多边形,直线,贝塞尔曲线…
我们先看一下Path中的几个枚举类型
Path.Direction
Specifies how closed shapes (e.g. rects, ovals) are oriented when they are added to a path
原文的意思是在绘制封闭的几何图形(例如矩形,椭圆…)时,使用的path是根据什么方向来的.这个方向指的是钟表的走向,顺时针:CW,逆时针:CCW.
具体用途,我们在下文的函数中在做详细介绍
Path.FillType
Enum for the ways a path may be filled.
用于表示填充路径的方式
- EVEN_ODD 奇偶规则
- WINDING 非零环绕数规则
- INVERSE_EVEN_ODD 反-奇偶规则
- INVERSE_WINDING 反-非零环绕数规则
我们使用Paint.Style.Fill给几何图形填充色值时,填充的集合图形的内部。一般简单的圆,矩阵……我们可以一样就看出它的内部和外部.但是对于一些自相交的多边形,有时候眼睛看到的和实际情况会出现差别,这时我们可与使用FillType中提到的两种方法来判断:
规则 | 描述 | 在内 | 在外 |
---|---|---|---|
奇-偶规则(Odd-even Rule) | 从任意点P构造一条射线(一条直线),从P向无穷大的任意方向,用这条射线找到C的所有交点,若为奇数,则P在多边形内部,否则在外部 | 相交点数为奇数 | 相交点数为偶数 |
非零环绕数规则(Nonzero Winding Number Rule) | 从任意点P构造一条射线(一条直线),从P向无穷大的任意方向。用这条射线找到与给定图形C上所有的焦点,判断焦点处的图形线段的方向:每一次顺时针交点(从左到右通过光线的曲线,从P点开始)减1;对于每一个逆时针交点(从右到左的曲线,从P点看)加1。如果总数为零,P在C外;否则,它是内部的。 | 不为零 | 为零 |
图示:
1.奇-偶规则(Odd-even Rule)
2.非零环绕数规则(Nonzero Winding Number Rule)
mPaint.style = Paint.Style.FILL
mPaint.color = Color.RED
canvas?.translate((width / 2).toFloat(), (height / 2).toFloat())
val path = Path()
// 叠加两个不同半径圆形组成自相交图形用来展示不同Direction下的非零环绕规则
path.addCircle(-250f, 0f, 100f, Path.Direction.CW);
path.addCircle(-250f, 0f, 200f, Path.Direction.CCW)
path.addCircle(250f, 0f, 100f, Path.Direction.CCW);
path.addCircle(250f, 0f, 200f, Path.Direction.CCW)
path.fillType = Path.FillType.WINDING
canvas?.drawPath(path, mPaint)
最后两个就不介绍了,这是一张Android APIDemo的示例图:
showPath(canvas, 0, 0, Path.FillType.WINDING, paint);
showPath(canvas, 160, 0, Path.FillType.EVEN_ODD, paint);
showPath(canvas, 0, 160, Path.FillType.INVERSE_WINDING, paint);
showPath(canvas, 160, 160, Path.FillType.INVERSE_EVEN_ODD, paint);