Path类使用详解
1、Path path=new Path();//空的
2、Path path=new Path(Path src);//创建一个新的路径,并从src路径获取内容赋值给新的路径
二、Path常用的一些方法
分类 | Path方法 | 备注 |
---|---|---|
点操作 | moveTo(float x,float y) | 设置接下来操作的起点位置为(x,y) |
rMoveTo(float x,float y) | 基于当前最后一个点位置移动(x,y)为坐标原点 | |
setLastPoint(float x,float y) | 改变前面操作中最后点的位置 | |
线操作 | lineTo(float x,float y) | 从当前点(上次操作结束的点)到(x,y)画直线 |
rLineTo(float x,float y) | 从当前点到移动(x,y)位置的点画直线 | |
常规图形 | addRect(RecF rect,Path.Direction dir) | 画矩形 |
addRect(float left,float top,float right,float bottom,Path.Direction dir) | ||
addRoundRect(RectF rect,float rx,float ry,Path.Direction dir) | 画圆角矩形radii指定四个角圆角半径,radii要至少8个值(多余的只取前8个) | |
addRoundRect(float left,float top,float right,float bottom,float rx,float ry,Path.Direction dir) | ||
addRoundRect(RectF rect,float[] radii,Path.Direction dir) | ||
addRoundRect(float left,float top,float right,float bottom,float[] radii,Path.Direction dir) | ||
addArc(RectF oval,float startAngle,float sweepAngle) | 画弧addArc是直接添加圆弧到path中,arcTo会判断要绘制的圆弧的起点与绘制圆弧前path中最后的点是否是同一个点,如果不是同一个点,并且forceMoveTo=false,就会连接两个点,默认forceMoveTo=false。 | |
addArc(float left,float top,float right,float bottom,float startAngle,float sweepAngle) | ||
arcTo(RectF oval,float startAngle,float sweepAngle,boolean forceMoveTo) | ||
arcTo(RectF oval,float startAngle,float sweepAngle) | ||
arcTo(float left,float top,float right,float bottom,float startAngle,float sweepAngle,boomean forceMoveTo) | ||
addCircle(float x,float y,float radius,Path.Direction dir) | 画圆 | |
addOval(RectF oval,Path.Direction dir) | 画椭圆 | |
addOval(float left,float top,float right,float bottom,Path.Direction dir) | ||
添加路径 | addPath(Path src) | 将src的路径添加到当前路径 |
addPath(path src,float x,float y) | 将src移动(x,y)距离后再添加进当前path | |
addPath(Path src,Matrix matrix) | 将src添加到当前路径之前先使用Matrix进行变换 | |
闭合 | close | 如果连接Path起点和终点能形成一个闭合图形,则会将起点和终点连接起来形成一个闭合图形。 |
贝塞尔曲线 | quadTo(float x1,float y1,float x2,float y2) | 绘制二阶贝塞尔曲线(x1,y1)为控制点,(x2,y2)为终点 |
rQuadTo(float x1,float y1,float x2,float y2) | 绘制二阶贝塞尔曲线(x1,y1)为控制点距离起点的偏移量(x2,y2)为终点距离起点的偏移量 | |
cubicTo(float x1,float y1,float x2,float y2,float x3,float y3) | 绘制三阶贝塞尔曲线(x1,y1)(x2,y2)为控制点(x3,y3)为终点 | |
rCubicTo(float x1,float y1,float x2,float y2,float x3,float y3) | 绘制三阶贝塞尔曲线(x1,y1)(x2,y2)为控制点距离起点的偏移量(x3,y3)为终点距离起点的偏移量 | |
是否为矩形 | isRect() | 判断Path是否是一个矩形 |
是否为空 | isEmpty() | 判断Path是否为空 |
替换路径 | set(Path src) | 用新的路径src替换当前路径的所有内容 |
平移路径对Path进行一段平移(和Canvas的translate相似,translate作用于整个画布,offset作用于当前path) | offset(float dx,float dy) | 将当前path平移(x,y) |
offset(float dx,float dy,Path dst) | 将当前path平移后的状态存入dst中,不会影响当前pathdst为null则会将平移作用于当前path | |
填充模式 | setFillType(Path.FillType ft) | 设置填充方式WINDING:非零环绕数规则INVERSE_WINDING:反非零环绕数规则EVEN_ODD:奇偶规则INVERSE_ODD:反奇偶规则 |
getFillType() | 获取填充模式 | |
isInverseFillType() | 判断是否是反向填充方式 | |
toggleInverseFillType() | 切换填充模式(原有规则与反向规则之间相互切换) | |
布尔操作 | op(Path path1,Path.Op op) | 对当前路径和path1路径执行布尔运算,运算方式有第二个参数指定,运算结果存入当前路径 |
op(Path path1,Path path2,Path.Op op) | 对path1和path2执行布尔运算,运算方式由第三个参数指定,运算结果存入当前路径 |
1、点操作
1)moveTo和rMoveTo
mPaint.setColor(Color.RED);
//将起点移动到(100,100)位置
mPath.moveTo(100,100);
mPath.lineTo(200, 200);
//将起点移动到(400,400)位置
mPath.rMoveTo(200,200);
mPath.lineTo(600,600);
canvas.drawPath(mPath,mPaint);
效果显示为:
2)moveTo、rMoveTo改变后面操作的起始点位置,setLastPoint改变前面操作中最后点的位置
moveTo:
mPaint.setColor(Color.RED);
mPath.lineTo(200, 0);
//将起点设置为(100,100)
mPath.moveTo(100, 100);
mPath.lineTo(200, 200);
mPath.lineTo(0,200);
mPath.close();
canvas.drawPath(mPath, mPaint);
显示效果是:
setLastPoint():
将上边的mPath.moveTo(100,100)换成mPath.setLastPoint(100,100)
mPaint.setColor(Color.RED);
mPath.lineTo(200, 0);
//改变前面操作中最后点的位置,即将(200,0)改成(100,100)
mPath.setLastPoint(100,100);
mPath.lineTo(200, 200);
mPath.lineTo(0,200);
mPath.close();
canvas.drawPath(mPath, mPaint);
显示效果是:
moveTo和setLastPoint的区别:
方法名 | 作用 | 是否影响之前的操作 | 是否影响起点 |
---|---|---|---|
moveTo | 移动下一次操作的起点位置 | 否 | 是 |
setLastPoint | 设置之前操作的最后一个点位置 | 是 | 否 |
2、线操作
mPaint.setColor(Color.RED);
mPath.lineTo(200, 400);
mPath.lineTo(400,600);
//画(400,600)到(800,1200)位置的线
mPath.rLineTo(400,600);
canvas.drawPath(mPath,mPaint);
效果图
3、常规图形
1)addArc和arcTo
forceMoveTo=true
mPaint.setColor(Color.RED);
RectF rectF1=new RectF(0,0,200,200);
mPath.addArc(rectF1,90,90);
RectF rectF2=new RectF(200,200,400,400);
mPath.arcTo(rectF2,0,90,true);
显示效果:
forceMoveTo=false 或者不设置
mPaint.setColor(Color.RED);
RectF rectF1=new RectF(0,0,200,200);
mPath.addArc(rectF1,90,90);
RectF rectF2=new RectF(200,200,400,400);
mPath.arcTo(rectF2,0,90,false);
//或者mPath.arcTo(rectF2,0,90);
canvas.drawPath(mPath,mPaint);
显示效果:
2)Path.Direction参数的作用:
点进去Direction,发现是一个枚举类型,里面只有两个枚举常量
CW:沿顺时针方向绘制
CCW:沿逆时针方向绘制
CW:
mPath.addCircle(0,0,300,Path.Direction.CW);
mPaint.setTextSize(30);
canvas.drawTextOnPath("唯一纯白的茉莉花,盛开在琥珀色月牙,就算失去所有爱的力量,我也不会害怕",mPath,0,0,mPaint);
canvas.drawPath(mPath,mPaint);
显示效果:
设置为CW时,path画圆的时候按照顺时针方向,所以文字也是按顺时针方向显示。
CCW:
mPath.addCircle(0,0,300,Path.Direction.CCW);
mPaint.setTextSize(40);
canvas.drawTextOnPath("唯一纯白的茉莉花,盛开在琥珀色月牙,就算失去所有爱的力量,我也不会害怕",mPath,0,0,mPaint);
canvas.drawPath(mPath,mPaint);
显示效果:
设置为CCW时,path画圆的时候按照逆时针方向,所以文字也是按逆时针方向显示。
CW:
mPath.addRect(-200,-200,200,200,Path.Direction.CW); mPath.setLastPoint(-100,100); canvas.drawPath(mPath,mPaint);
显示效果:
设置为CW顺时针方向的时候,绘制矩形是从起始位置(-200,-200)到(-200,200)画矩形,这个时候设置setLastPoint(-100,100),也就是原来(-200,200)的位置被(-100,100)代替了。
CCW:
mPath.addRect(-200,-200,200,200,Path.Direction.CCW); mPath.setLastPoint(-100,100); canvas.drawPath(mPath,mPaint);
显示效果:
设置为CCW逆时针方向的时候,绘制矩形是从起始位置(-200,-200)到(200,-200)画矩形,这个时候设置setLastPoint(-100,100),也就是原来(200,-200)的位置被(-100,100)代替了。
4、添加路径
addPath(Path src,float x,float y):
Path src = new Path(); src.addCircle(0, 0, 100, Path.Direction.CW); mPath.addCircle(0, 0, 100, Path.Direction.CW); mPath.addPath(src, 0, 100); canvas.drawPath(mPath,mPaint);
显示效果:
5、替换路径
Path src = new Path(); src.addCircle(200, 0, 100, Path.Direction.CW); mPath.addCircle(0, 0, 100, Path.Direction.CW); mPath.set(src); canvas.drawPath(mPath, mPaint);
显示效果:
6、偏移路径
1)offset(float dx,float dy)
mPath.addCircle(0, 0, 100, Path.Direction.CW); mPath.offset(0, 200); canvas.drawPath(mPath, mPaint);
显示效果:
2)offset(float dx,float dy,Path dst)
Path dst = new Path(); mPath.addCircle(0, 0, 100, Path.Direction.CW); mPath.offset(0, 200, dst); canvas.drawPath(mPath, mPaint); mPaint.setColor(Color.GREEN); canvas.drawPath(dst, mPaint);
显示效果:
7、填充模式
在Path中,有四种填充模式:
填充模式 | 备注 |
---|---|
WINDING | 非零环绕数规则 |
INVERSE_WINDING | 反非零环绕数规则 |
EVEN_ODD | 奇偶规则 |
INVERSE_WINDING | 反奇偶规则 |
WINDING:
非零环绕原则:首先,它需要你图形中的所有线条都是有绘制方向的:
然后,从平面中的点向任意方向射出一条射线,以0为初始值,对于射线和图形的所有交点,每遇到顺时针的交点,把结果加1,每遇到逆时针的交点,把结果减1,最终把所有的交点都算上,得到的结果如果不是0,则认为这个点在图形内部,是要被
涂色的区域;如果是0,则认为这个点在图形外部,是不被涂色的区域。
EVEN_ODD:
奇偶原则,对于平面中的任意一点,向任意方向射出一条射线,这条射线和图形相交的次数(必须是相交,相切不算)如果是奇数,则这个点被认为在图形内部,是要被涂色的区域;如果是偶数,则这个点被认为在图形外部,是不被涂色的区域。
INVERSE_WINDING和INVERSE_ODD只是把两种效果进行反转。
几个效果图:
8、布尔运算
布尔运算可以指定不同的布尔操作方式:
参数 | 备注 |
---|---|
DIFFERENCE | path1不同于path2的区域 |
REVERSEDIFFERENCE | path2不同于path1的区域 |
INTERSECT | path1与path2相交区域 |
UNION | path1与path2的和 |
XOR | path1与path2和并减去重叠的部分 |
DIFFERENCE:
Path path1 = new Path(); path1.addCircle(0, 0, 100, Path.Direction.CW); mPath.addCircle(0, 50, 100, Path.Direction.CW); mPath.op(path1, Path.Op.DIFFERENCE); canvas.drawPath(mPath, mPaint);
显示效果:
REVERSEDIFFERENCE:
Path path1 = new Path(); path1.addCircle(0, 0, 100, Path.Direction.CW); mPath.addCircle(0, 50, 100, Path.Direction.CW); mPath.op(path1, Path.Op.REVERSE_DIFFERENCE); canvas.drawPath(mPath, mPaint);
显示效果:
INTERSECT:
Path path1 = new Path(); path1.addCircle(0, 0, 100, Path.Direction.CW); mPath.addCircle(0, 50, 100, Path.Direction.CW); mPath.op(path1, Path.Op.INTERSECT); canvas.drawPath(mPath, mPaint);
显示效果:
UNION:
Path path1 = new Path();
path1.addCircle(0, 0, 100, Path.Direction.CW);
mPath.addCircle(0, 50, 100, Path.Direction.CW);
mPath.op(path1, Path.Op.UNION);
canvas.drawPath(mPath, mPaint);
显示效果:
XOR:
Path path1 = new Path();
path1.addCircle(0, 0, 100, Path.Direction.CW);
mPath.addCircle(0, 50, 100, Path.Direction.CW);
mPath.op(path1, Path.Op.XOR);
canvas.drawPath(mPath, mPaint);
显示效果: