Path
总结
作用 |
相关方法 |
备注 |
移动起点 |
moveTo |
移动下一次操作的起点位置 |
设置终点 |
setLastPoint |
重置当前path中最后一个点位置,如果在绘制之前调用,效果和moveTo相同 |
连接直线 |
lineTo |
添加上一个点到当前点之间的直线到Path |
闭合路径 |
close |
连接第一个点连接到最后一个点,形成一个闭合区域 |
添加内容 |
addRect, addRoundRect, addOval, addCircle, addPath, addArc, arcTo |
添加(矩形, 圆角矩形, 椭圆, 圆, 路径, 圆弧) 到当前Path (注意addArc和arcTo的区别) |
是否为空 |
isEmpty |
判断Path是否为空 |
是否为矩形 |
isRect |
判断path是否是一个矩形 |
替换路径 |
set |
用新的路径替换到当前路径所有内容 |
偏移路径 |
offset |
对当前路径之前的操作进行偏移(不会影响之后的操作) |
贝塞尔曲线 |
quadTo, cubicTo |
分别为二次和三次贝塞尔曲线的方法 |
rXxx方法 |
rMoveTo, rLineTo, rQuadTo, rCubicTo |
不带r的方法是基于原点的坐标系(偏移量), rXxx方法是基于当前点坐标系(偏移量) |
填充模式 |
setFillType, getFillType, isInverseFillType, toggleInverseFillType |
设置,获取,判断和切换填充模式 |
提示方法 |
incReserve |
提示Path还有多少个点等待加入(这个方法貌似会让Path优化存储结构) |
布尔操作(API19) |
op |
对两个Path进行布尔运算(即取交集、并集等操作) |
计算边界 |
computeBounds |
计算Path的边界 |
重置路径 |
reset, rewind |
清除Path中的内容,reset不保留内部数据结构,但会保留FillType,rewind会保留内部的数据结构,但不保留FillType |
矩阵操作 |
transform |
矩阵变换 |
moveTo、 setLastPoint、 lineTo 和 close
- lineTo 从前一个操作的点到下一个点画一条线
- movteTo与setLastPoint
方法名 |
简介 |
是否影响之前的操作 |
是否影响之后操作 |
moveTo |
移动下一次操作的起点位置 |
否 |
是 |
setLastPoint |
设置之前操作的最后一个点位置 |
是 |
是 |
moveTo示例
moveTo绝对坐标,rMoveTo相对坐标
canvas.translate(mWidth / 2, mHeight / 2);
Path path = new Path();
path.lineTo(200, 200);
path.moveTo(200,100);
path.lineTo(200,0);
canvas.drawPath(path, mPaint);

canvas.translate(mWidth / 2, mHeight / 2);
Path path = new Path();
path.lineTo(200, 200);
path.setLastPoint(200,100);
path.lineTo(200,0);
canvas.drawPath(path, mPaint);

- close方法用于连接当前最后一个点和最初的一个点,最终形成一个封闭的图形。
- 不是所有的子图形都需要使用 close() 来封闭。当需要填充图形时(即 Paint.Style 为 FILL 或 FILL_AND_STROKE),Path 会自动封闭子图形

paint.setStyle(Style.FILL);
path.moveTo(100, 100);
path.lineTo(200, 100);
path.lineTo(150, 150);
addXxx与arcTo
基本形状
public void addCircle (float x, float y, float radius, Path.Direction dir)
public void addOval (RectF oval, Path.Direction dir)
public void addRect (float left, float top, float right, float bottom, Path.Direction dir)
public void addRect (RectF rect, Path.Direction dir)
public void addRoundRect (RectF rect, float[] radii, Path.Direction dir)
public void addRoundRect (RectF rect, float rx, float ry, Path.Direction dir)
- Path.Direction: CW,顺时针,CCW 逆时针
- Path.Direction有两个作用,一个是在添加图形时确定闭合顺序(各个点的记录顺序),另一个是对图形的渲染结果有影响(是判断图形渲染的重要条件)
canvas.translate(mWidth / 2, mHeight / 2);
Path path = new Path();
path.addRect(-200,-200,200,200, Path.Direction.CW);
path.setLastPoint(-300,300);
canvas.drawPath(path,mPaint);

canvas.translate(mWidth / 2, mHeight / 2);
Path path = new Path();
path.addRect(-200,-200,200,200, Path.Direction.CCW);
path.setLastPoint(-300,300);
canvas.drawPath(path,mPaint);

addPath
public void addPath (Path src)
public void addPath (Path src, float dx, float dy)
public void addPath (Path src, Matrix matrix)
addArc与arcTo
public void addArc (RectF oval, float startAngle, float sweepAngle)
public void arcTo (RectF oval, float startAngle, float sweepAngle)
public void arcTo (RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)
名称 |
作用 |
区别 |
addArc |
添加一个圆弧到path |
直接添加一个圆弧到path中 |
arcTo |
添加一个圆弧到path |
添加一个圆弧到path,如果圆弧的起点和上次最后一个坐标点不相同,就连接两个点 |
forceMoveTo |
含义 |
等价方法 |
true |
将最后一个点移动到圆弧起点,即不连接最后一个点与圆弧起点 |
public void addArc (RectF oval, float startAngle, float sweepAngle) |
false |
不移动,而是连接最后一个点与圆弧起点 |
public void arcTo (RectF oval, float startAngle, float sweepAngle) |
- sweepAngle取值范围是 [-360, 360),当 >= 360 或者 < -360 时将不会绘制任何内容
- addArc() 只是一个直接使用了 forceMoveTo = true 的简化版 arcTo()
贝塞尔曲线
public void quadTo(float x1, float y1, float x2, float y2)
public void rQuadTo(float dx1, float dy1, float dx2, float dy2)
public void cubicTo(float x1, float y1, float x2, float y2,
float x3, float y3)
public void rCubicTo(float x1, float y1, float x2, float y2,
float x3, float y3)
二阶贝塞尔曲线
- 开始点A,终点C,控制点B,连接AB,BC
- 在AB上找一点D,BC上找一点E,使得AD:AB=BE:BC
- 连接DE,在DE上找一点F,使得DF:DE=AD:AB=BE:BC
- 从开始移动点D生成曲线


三阶贝塞尔曲线
- 与二阶类似
- AE:AB = BF:BC=CG:CD=EH:EF=FI:FG=HJ:HI
- 其中I就是曲线上的一点

FillType
public void setFillType(FillType ft)
public enum FillType {
WINDING(0),
EVEN_ODD(1),
INVERSE_WINDING (2),
INVERSE_EVEN_ODD(3);
FillType(int ni) {
nativeInt = ni;
}
final int nativeInt;
}
- 都是针对封密图形
- EVEN_ODD表示奇偶规则,而INVERSE_EVEN_ODD表示奇偶规则的反色版本
- WINDING表示非零环绕数规则,而INVERSE_WINDING表示对应的反色版本
奇偶规则
- 奇数表示在图形内,偶数表示在图形外
- 从任意位置p作一条射线, 若与该射线相交的图形边的数目为奇数,则p是图形内部点,否则是外部点。

- P1: 从P1发出一条射线,发现图形与该射线相交边数为0,偶数,故P1点在图形外部。
- P2: 从P2发出一条射线,发现图形与该射线相交边数为1,奇数,故P2点在图形内部。
- P3: 从P3发出一条射线,发现图形与该射线相交边数为2,偶数,故P3点在图形外部。
非零环绕数规则
- 首先,它需要你图形中的所有线条都是有绘制方向的(Path.Direction指定)
- 若环绕数为0表示在图形外,非零表示在图形内
- 然后,同样是从平面中的点向任意方向射出一条射线,但计算规则不一样:以 0 为初始值,对于射线和图形的所有交点,遇到每个顺时针的交点(图形从射线的左边向右穿过)把结果加 1,遇到每个逆时针的交点(图形从射线的右边向左穿过)把结果减 1,最终把所有的交点都算上,得到的结果如果不是 0,则认为这个点在图形内部,是要被涂色的区域;如果是 0,则认为这个点在图形外部,是不被涂色的区域。

布尔操作
public boolean op(Path path, Op op)
public boolean op(Path path1, Path path2, Op op)
path1.op(path2, Path.Op.DIFFERENCE);
path3.op(path1, path2, Path.Op.DIFFERENCE)
- 布尔操作是两个Path之间的运算,主要作用是用一些简单的图形通过一些规则合成一些相对比较复杂,或难以直接得到的图
DIFFERENCE

REVERSE_DIFFERENCE

INTERSECT

UNION

XOR
- 异或
- 包含Path1与Path2但不包括两者相交的部分

重置路径
public void reset() {
isSimplePath = true;
mLastDirection = null;
if (rects != null) rects.setEmpty();
final FillType fillType = getFillType();
nReset(mNativePath);
setFillType(fillType);
}
public void rewind() {
isSimplePath = true;
mLastDirection = null;
if (rects != null) rects.setEmpty();
nRewind(mNativePath);
}
方法 |
是否保留FillType设置 |
是否保留原有数据结构 |
reset |
是 |
否 |
rewind |
否 |
是 |
其它函数
public boolean isEmpty ()
public boolean isRect (RectF rect)
public void set (Path src)
public void offset (float dx, float dy)
public void offset (float dx, float dy, Path dst)
void computeBounds (RectF bounds, boolean exact)