在 Canvas 的学习中,只能画一些比较规则的图形,如方形,圆,弧线等。如果要画一些比较复杂的图形,只要计算好坐标,就需用到 Path 类就能做到,以及著名的贝塞尔曲线也是用 Path 来实现。这里列举下 Path 常用的方法。
画笔等相关设置为:
private void init() {
mPaint = new Paint();
mPaint.setColor(Color.parseColor("#2d6fff"));
mPaint.setStyle(Paint.Style.STROKE); //设置画笔模式为描边
mPaint.setStrokeWidth(10f); //设置画笔宽度为10px
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPath = new Path();
}
1. lineTo
void | lineTo(float x, float y) Add a line from the last point to the specified point (x,y). |
此方法传入的参数为点的 x,y 坐标,表示的上次画笔的位置到目标点的位置的连线。一开始画笔的位置为(0,0)。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.parseColor("#dcdcdc"));
mPath.lineTo(200,200);
mPath.lineTo(200,0);
canvas.drawPath(mPath,mPaint);
}
从(0,0)到点(200,200),形成连线,这样画笔的位置就到了(200,200)。再次将画笔的位置移动到点(200,0),形成新的连线。
效果:
2. moveTo
用于移动下一次操作的起点位置。
void | moveTo(float x, float y) Set the beginning of the next contour to the point (x,y). |
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.parseColor("#dcdcdc"));
mPath.lineTo(200, 200);
mPath.lineTo(200, 0);
//经过这样的移动,起点位置为(200,0)
//将起点移动到(200,200)
mPath.moveTo(200, 200);
//再次连线到点(400,0)
mPath.lineTo(400, 0);
canvas.drawPath(mPath, mPaint);
}
效果:
3. close
void | close() Close the current contour. |
用于连接第一个点连接到最后一个点,形成一个闭合区域。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.parseColor("#dcdcdc"));
mPath.moveTo(200,200);
mPath.lineTo(200,400);
mPath.lineTo(400,400);
canvas.drawPath(mPath, mPaint);
}
未调用 close 时候的效果:
调用 close 方法后,形成闭合:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.parseColor("#dcdcdc"));
mPath.moveTo(200,200);
mPath.lineTo(200,400);
mPath.lineTo(400,400);
mPath.close();
canvas.drawPath(mPath, mPaint);
}
效果:
4. addRect, addRoundRect, addOval, addCircle
此四个方法与 Canvas 中的方法类似,这里就只列举 addRect 的用法:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.parseColor("#dcdcdc"));
RectF rectF = new RectF(200,200,500,500);
mPath.addRect(rectF, Path.Direction.CW);
canvas.drawPath(mPath, mPaint);
}
其中 Path.Direction 中存在两种:
Path.Direction.CW
Path.Direction.CCW
类型 | 解释 | 翻译 |
---|---|---|
CW | clockwise | 顺时针 |
CCW | counter-clockwise | 逆时针 |
这里是指在画图的时候按照顺时针或者逆时针的顺序进行画图。
5. addPath
用于将两个 Path 合并:
void | addPath(Path src, Matrix matrix) Add a copy of src to the path, transformed by matrix |
void | addPath(Path src) Add a copy of src to the path |
void | addPath(Path src, float dx, float dy) Add a copy of src to the path, offset by (dx,dy) |
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.parseColor("#dcdcdc"));
RectF rectF = new RectF(200, 200, 500, 500);
mPath.addRect(rectF, Path.Direction.CW);
mPathSecond.addCircle(200, 350, 150, Path.Direction.CCW);
mPath.addPath(mPathSecond);
canvas.drawPath(mPath, mPaint);
}
效果:
6. addArc 和 arcTo
名称 | 作用 | 区别 |
---|---|---|
addArc | 添加一个圆弧到path | 直接添加一个圆弧到path中 |
arcTo | 添加一个圆弧到path | 添加一个圆弧到path,如果圆弧的起点和上次最后一个坐标点不相同,就连接两个点 |
addArc:
void | addArc(float left, float top, float right, float bottom, float startAngle,float sweepAngle) Add the specified arc to the path as a new contour. |
void | addArc(RectF oval, float startAngle, float sweepAngle) Add the specified arc to the path as a new contour. |
arcTo:
void | arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo) Append the specified arc to the path as a new contour. |
void | arcTo(float left, float top, float right, float bottom, float startAngle,float sweepAngle, boolean forceMoveTo) Append the specified arc to the path as a new contour. |
void | arcTo(RectF oval, float startAngle, float sweepAngle) Append the specified arc to the path as a new contour. |
forceMoveTo 的作用:
forceMoveTo | 含义 | 等价方法 |
---|---|---|
true | 将最后一个点移动到圆弧起点,即不连接最后一个点与圆弧起点 | public void addArc (RectF oval, float startAngle, float sweepAngle) |
false | 不移动,而是连接最后一个点与圆弧起点 | public void arcTo (RectF oval, float startAngle, float sweepAngle) |
forceMoveTo 为 true 的时候:
forceMoveTo 为 false 的时候:
代码如下:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.parseColor("#dcdcdc"));
RectF oval = new RectF(200, 200, 500, 500);
mPath.lineTo(100, 300);
mPath.arcTo(oval, 0, 270, false);
canvas.drawPath(mPath, mPaint);
}
7. 二阶贝塞尔曲线
二阶曲线由两个数据点,一个控制点来描述曲线状态。二阶曲线对应的方法是 quadTo :
void | quadTo(float x1, float y1, float x2, float y2) Add a quadratic bezier from the last point, approaching control point (x1,y1), and ending at (x2,y2). |
其中,起点为 Path的起点,控制点为 x1,y1,终点为 x2,y2。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.parseColor("#dcdcdc"));
mPath.moveTo(100, 100);
mPath.quadTo(200, 200, 500, 100);
canvas.drawPath(mPath, mPaint);
}
效果:
8. 三阶贝塞尔曲线
三阶曲线由两个数据点,两个控制点来描述曲线状态。三阶曲线对应的方法是 cubicTo :
void | cubicTo(float x1, float y1, float x2, float y2, float x3, float y3) Add a cubic bezier from the last point, approaching control points (x1,y1) and (x2,y2), and ending at (x3,y3). |
其中,起点为 Path的起点,终点为 x3,y3,控制点为 x1,y1 和 x2,y2。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.parseColor("#dcdcdc"));
mPath.moveTo(100, 100);
mPath.cubicTo(200, 500, 400, 300, 500, 100);
canvas.drawPath(mPath, mPaint);
}
效果:
参考:
https://www.gcssloop.com/customview/Path_Over