一、通过drawPath()绘制自定义图形
Path可以描述直线、二次曲线、三次曲线、圆、椭圆、弧形、矩形、圆角矩形。Path有两类方法,一类是直接描述路径的,另一类是辅助的设置或计算。
二、Path方法第一类:直接描述路径
这类方法可以细分为两组:添加子图形和画线(直线或曲线)
1、addXXX():添加子图形
addCircle(float x, float y, float radius, Direction dir) 添加圆
/**
*
* @param x
* @param y
* @param radius
* @param dir 画圆的路径的方向
*/
addCircle(float x, float y, float radius, Direction dir) 添加圆
注:路径方向有两种:顺时针 (CW clockwise) 和逆时针 (CCW counter-clockwise)。 对于普通情况,这个参数填 CW 还是填 CCW 没有影响。它只是在需要填充图形 (Paint.Style 为 FILL 或 FILL_AND_STROKE) ,并且图形出现自相交时,用于判断填充范围的。
例子:添加一个圆
path.addCircle(300, 300, 200, Path.Direction.CW);
......
canvas.drawPath(path, paint);
Path.add-()其他方法
- addOval(float left, float top, float right, float bottom, Direction dir) / addOval(RectF oval, Direction dir)添加椭圆
- addRect(float left, float top, float right, float bottom, Direction dir) / addRect(RectF rect, Direction dir) 添加矩形
- addRoundRect(RectF rect, float rx, float ry, Direction dir) / addRoundRect(float left, float top, float right, float bottom, float rx, float ry, Direction dir) / addRoundRect(RectF rect, float[] radii, Direction dir) / addRoundRect(float left, float top, float right, float bottom, float[] radii, Direction dir) 添加圆角矩形
- addPath(Path path) 添加另一个 Path
2、xxxTo() ——画线(直线或曲线)
(1)lineTo(float x, float y) / rLineTo(float x, float y) 画直线
/**
*
* @param x 目标位置X
* @param y 目标位置y
*/
lineTo(float x, float y)
从当前位置向目标位置画一条直线, x 和 y 是目标位置的坐标。这两个方法的区别是,lineTo(x, y) 的参数是绝对坐标,而 rLineTo(x, y) 的参数是相对当前位置的相对坐标 (前缀 r 指的就是 relatively 「相对地」)。
当前位置:所谓当前位置,即最后一次调用画 Path 的方法的终点位置。初始值为原点 (0, 0)。
paint.setStyle(Paint.Style.STROKE);
path.lineTo(100, 100); // 由当前位置 (0, 0) 向 (100, 100) 画一条直线
path.rLineTo(100, 0); // 由当前位置 (100, 100) 向正右方 100 像素的位置画一条直线
canvas.drawPath(path, paint);
连线
(2)quadTo(float x1, float y1, float x2, float y2) / rQuadTo(float dx1, float dy1, float dx2, float dy2) 画二次贝塞尔曲线
参数:这条二次贝塞尔曲线的起点就是当前位置,而参数中的 x1, y1 和 x2, y2 则分别是控制点和终点的坐标。和 rLineTo(x, y) 同理,rQuadTo(dx1, dy1, dx2, dy2) 的参数也是相对坐标
(3)cubicTo(float x1, float y1, float x2, float y2, float x3, float y3) / rCubicTo(float x1, float y1, float x2, float y2, float x3, float y3) 画三次贝塞尔曲线
(4)moveTo(float x, float y) / rMoveTo(float x, float y) 移动到目标位置
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(10);
path.lineTo(100, 100); // 画斜线
path.moveTo(200, 200); // 我移~~
path.lineTo(200, 0); // 画竖线
canvas.drawPath(path, paint);
移动位置
(5)arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo) / arcTo(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean forceMoveTo) / arcTo(RectF oval, float startAngle, float sweepAngle) 画弧形
参数 forceMoveTo :绘制是要「抬一下笔移动过去」,还是「直接拖着笔过去」,区别在于是否留下移动的痕迹。
addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle) / addArc(RectF oval, float startAngle, float sweepAngle)
(6)close() 封闭当前子图形
作用是把当前的子图形封闭,即由当前位置向当前子图形的起点绘制一条直线。
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(10);
path.moveTo(100, 100);
path.lineTo(200, 100);
path.lineTo(150, 150);
path.close();
canvas.drawPath(path, paint);
1.png
2.png
当需要填充,不需要close() 。Paint.Style 为 FILL 或 FILL_AND_STROKE,Path 会自动封闭子图形。
paint.setStyle(Paint.Style.FILL);
paint.setStrokeWidth(10);
path.moveTo(100, 100);
path.lineTo(200, 100);
path.lineTo(150, 150);
canvas.drawPath(path, paint);
填充
三、Path方法第二类:辅助的设置或计算
1.Path.setFillType(Path.FillType ft) 设置填充方式
在二.1画圆中,参数 Direction dir提到, Path.setFillType(fillType) 是用来设置图形自相交时的填充算法的,不同的FillType值,有不同的填充效果。FillType的四种取值:
- EVEN_ODD
- WINDING (默认值)
- INVERSE_EVEN_ODD
- INVERSE_WINDING
(1)EVEN_ODD
即 even-odd rule (奇偶原则):对于平面中的任意一点,向任意方向射出一条射线,这条射线和图形相交的次数(相交才算,相切不算哦)如果是奇数,则这个点被认为在图形内部,是要被涂色的区域;如果是偶数,则这个点被认为在图形外部,是不被涂色的区域。射线每穿过图形中的一条线,内外状态就发生一次切换,这就是为什么 EVEN_ODD 是一个「交叉填充」的模式。
(2)WINDING
non-zero winding rule (非零环绕数原则),首先,它需要你图形中的所有线条都是有绘制方向的:以 0 为初始值,顺时针+1,逆时针-1。结果不为0,则在图形内部,涂色;结果为0,则在图形外部,不被涂色。
(3)INVERSE_EVEN_ODD和 INVERSE_WINDING
与前两个相反
网友评论