Android Canvas之Path *** 作

Android Canvas之Path *** 作,第1张

概述接上篇,Android自定义View工具:Paint&Canvas(二)上一篇中介绍的Canvas绘制图形只能画一些常规图形(圆,椭圆,矩形等),如果想绘制更复杂的图形,Path神器来了!Path是什么?Path类将多种复合路径(多个轮廓,如直线段、二次曲线、立方曲线)封装在其内部的几何路径。如何绘制Path:通过设置Pain

接上篇,@L_404_0@

上一篇中介绍的Canvas绘制图形只能画一些常规图形(圆,椭圆,矩形等),如果想绘制更复杂的图形,Path神器来了!

Path是什么?
Path类将多种复合路径(多个轮廓,如直线段、二次曲线、立方曲线)封装在其内部的几何路径。

如何绘制Path:
通过设置Paint的Style(FILL、stroke、FILL_AND_stroke),然后调用canvas.drawPath(path, paint);Path还可以用于剪切或者在路径上绘制文本(canvas.drawTextOnPath())。

Path有两个构造函数:

Path() // 空的构造函数Path(Path src) //创建一个新的路径,并且从src路径里赋值内容

Path常用方法一览表:

Path常用方法备注
线 *** 作
lineto、rlineto绘制线
点 *** 作
moveto、rMoveto改变后面 *** 作的起始点位置
setLastPoint改变前面 *** 作中最后点的位置
添加常规图形
addRect绘制矩形
addRoundRect绘制圆角矩形
addCircle绘制圆
addoval绘制椭圆
addArc、arcTo绘制圆弧
闭合path
close如果连接Path起点和终点能形成一个闭合图形,则会将起点和终点连接起来形成一个闭合图形
贝塞尔曲线
quadTo、rQuadTo、cubicTo、rCubicTo贝塞尔曲线
线 *** 作
lineto(float x, float y) //添加当前点到目标点(x,y)构成的直线到pathrlineto(float dx, float dy) //基于当前坐标系,即以path最后的那个点//为坐标系原点(0,0),如果前面没有path的点,默认是屏幕左上角(0,0).

注:lineto、rlineto起始点默认是屏幕左上角的坐标系原点(0,0)!
示例:

//设置PaintPaint paint = new Paint();paint.setcolor(color.RED);paint.setStyle(Paint.Style.stroke);paint.setstrokeWIDth(10f);//设置PathPath path = new Path();//屏幕左上角(0,0)到(200,400)画一条直线path.lineto(200, 400);//(200, 400)到(400,600)画一条直线path.lineto(400, 600);//以(400,600)为起始点(0,0)偏移量为(400,600)画一条直线,//其终点坐标实际在屏幕的位置为(800,1200)path.rlineto(400, 600);canvas.drawPath(path, mPaint);

效果图:

点 *** 作
moveto(float x, float y) //改变接下来 *** 作的起点位置为(x,y)rMoveto(float dx, float dy) //接下来要 *** 作的起点位置为(x+dx,y+dy)setLastPoint(float dx, float dy) //改变前一步 *** 作点的位置,会改变前一步的 *** 作

先来看moveto和rMoveto的区别,示例:

//初始化PaintPaint paint = new Paint();paint.setcolor(color.RED);paint.setStyle(Paint.Style.stroke);paint.setstrokeWIDth(10f);//初始化PathPath path = new Path();//将坐标系原点从(0,0)移动到(100,100)path.moveto(100, 100);//画从(100,100)到(400,400)之间的直线path.lineto(400, 400);//path.rMoveto(0, 100); //暂时注释path.lineto(400, 800);canvas.drawPath(path, mPaint);

效果图:

上面代码中,打开注释的path.rMoveto(0, 100),意为下一步 *** 作起点位置由(400,400)变为(400+0,400+100)即为(400,500),效果图:

接下来看下,moveto和setLastPoint的区别,同样用上面的代码,加上path.setLastPoint(100, 800),如下:

//初始化PaintPaint paint = new Paint();paint.setcolor(color.RED);paint.setStyle(Paint.Style.stroke);paint.setstrokeWIDth(10f);//初始化PathPath path = new Path();//将坐标系原点从(0,0)移动到(100,100)path.moveto(100, 100);//画从(100,100)到(400,400)之间的直线path.lineto(400, 400);//新加的setLastPointpath.setLastPoint(100, 800);path.lineto(400, 800);canvas.drawPath(path, mPaint);

效果图:

虚线本来是没设置setLastPoint之前的路径,设置setLastPoint(100,800)后,影响到了前一步lineto(400,400) *** 作,变成了lineto(100,800),最后结果就变成了红颜色的path路径,可以得出结论:moveto影响的是后面 *** 作的起点位置,不会影响之前的 *** 作;而 setLastPoint改变前一步 *** 作最后一个点的位置,不仅影响前一步 *** 作,同时也会影响后一步 *** 作!

绘制常规图形
//绘制圆addCircle(float x, float y, float radius, Direction dir)  //绘制椭圆addoval(RectF oval, Direction dir)addoval(float left, float top, float right, float bottom, Direction dir) //绘制矩形addRect(RectF rect, Direction dir) addRect(float left, float top, float right, float bottom, 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)

所有方法里面都有一个共同的参数Direction :

Direction备注
Path.Direction.ccwcounter-clockwise ,沿逆时针方向绘制
Path.Direction.CWclockwise ,沿顺时针方向绘制

Direction 用法示例:

//初始化PaintPaint paint = new Paint();paint.setcolor(color.RED);paint.setStyle(Paint.Style.stroke);paint.setstrokeWIDth(2f);paint.setTextSize(40f);//初始化PathPath path = new Path();//以(600,600)为圆心,300为半径绘制圆 //Path.Direction.CW顺时针绘制圆 Path.Direction.ccw逆时针绘制圆path.addCircle(600, 600, 300, Path.Direction.CW);//沿path绘制文字canvas.drawTextOnPath("痛苦最好是别人的,快乐才是自己的;麻烦将是暂时的,朋友总是永恒的。", path, 0, 0, paint);canvas.drawPath(path, paint);

效果图:


效果很明显,设置为Path.Direction.CW时,文字沿顺时针绘制;设置为Path.Direction.ccw时,文字沿逆时针绘制。

绘制常规图形示例:

//初始化PaintPaint paint = new Paint();paint.setcolor(color.RED);paint.setStyle(Paint.Style.stroke);paint.setstrokeWIDth(10f);Path path = new Path();//以(400,200)为圆心,半径为100绘制圆path.addCircle(400, 200, 100, Path.Direction.CW);//绘制椭圆RectF rectF = new RectF(100, 350, 500, 600);//第一种方法绘制椭圆path.addoval(rectF, Path.Direction.CW);//第二种方法绘制椭圆path.addoval(600, 350, 1000, 600, Path.Direction.CW);//绘制矩形RectF rect = new RectF(100, 650, 500, 900);//第一种方法绘制矩形path.addRect(rect, Path.Direction.CW);//第一种方法绘制矩形path.addRect(600, 650, 1000, 900, Path.Direction.ccw);//绘制圆角矩形RectF roundRect = new RectF(100, 950, 300, 1100);//第一种方法绘制圆角矩形path.addRoundRect(roundRect, 20, 20, Path.Direction.CW);//第二种方法绘制圆角矩形path.addRoundRect(350, 950, 550, 1100, 10, 50, Path.Direction.ccw);//第三种方法绘制圆角矩形 //float[] radii中有8个值,依次为左上角,右上角,右下角,左下角的rx,ryRectF roundRectT = new RectF(600, 950, 800, 1100);path.addRoundRect(roundRectT, new float[]{50, 50, 50, 50, 50, 50, 0, 0}, Path.Direction.ccw);//第四种方法绘制圆角矩形path.addRoundRect(850, 950, 1050, 1100,new float[]{0, 0, 0, 0,50, 50, 50, 50}, Path.Direction.ccw);canvas.drawPath(path, paint);

效果图:

绘制圆弧:

//绘制圆弧addArc(RectF oval, float startAngle, float sweepAngle)addArc(float left, float top, float right, float bottom, float startAngle,float sweepAngle)//forceMoveto:是否强制将path最后一个点移动到圆弧起点,//true是强制移动,即为不连接两个点;false则连接两个点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, boolean forceMoveto)

addArc和arcTo都是添加圆弧到path中,不过他们之间还是有区别的:addArc是直接添加圆弧到path中,而arcTo会判断要绘制圆弧的起点与绘制圆弧之前path中最后的点是否是同一个点,如果不是同一个点的话,就会连接两个点。
示例:

//在(400, 200, 600, 400)区域内绘制一个300度的圆弧RectF rectF = new RectF(400, 200, 600, 400);path.addArc(rectF, 0, 300);//在(400, 600, 600, 800)区域内绘制一个90度的圆弧,并且不连接两个点RectF rectFTo = new RectF(400, 600, 600, 800);path.arcTo(rectFTo, 0, 90, true);//等价于path.addArc(rectFTo, 0, 90);canvas.drawPath(path, paint);

效果图:

修改一下代码:

//在(400, 200, 600, 400)区域内绘制一个300度的圆弧RectF rectF = new RectF(400, 200, 600, 400);path.addArc(rectF, 0, 300);//在(400, 600, 600, 800)区域内绘制一个90度的圆弧,并且连接两个点RectF rectFTo = new RectF(400, 600, 600, 800);path.arcTo(rectFTo, 0, 90,false);//等价于path.arcTo(rectFTo, 0, 90);canvas.drawPath(path, paint);

对比发现我们只是将arcTo最后一个参数变成了false,即连接绘制圆弧之前path的最后一个点和绘制圆弧的起点,效果图:

闭合path
path.close();

如果path的终点和起始点不是同一个点的话,close()连接这两个点,形成一个封闭的图形,示例:

//初始化PaintPaint paint = new Paint();paint.setcolor(color.RED);paint.setStyle(Paint.Style.stroke);paint.setstrokeWIDth(10f);//初始化PathPath path = new Path();//将坐标原点移动到(300,300,)path.moveto(300, 300);//连接(300, 300)和(300, 600)成一条线path.lineto(300, 600);//连接(300, 600)和(600, 600)成一条线path.lineto(600, 600);//path.close();暂时注释canvas.drawPath(path, paint);

效果图:

修改一下代码,将上面的path.close()打开,效果图:

可以调用close()后,连接了path的起始点和终点形成了一个封闭图形!

贝塞尔曲线内容较多,放在下一篇了!

总结

以上是内存溢出为你收集整理的Android Canvas之Path *** 作全部内容,希望文章能够帮你解决Android Canvas之Path *** 作所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1035617.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-24
下一篇 2022-05-24

发表评论

登录后才能评论

评论列表(0条)

保存