path这个类在图形的绘制中十分重要,它可以画出我们前面学过的基础图形,也可以画出我们前面画不出来的不规则图形,特别是使用贝塞尔曲线我们可以做出吊炸天的特效。十分向往吧、内心是不是有点小激动!接下来便继续深入----开启path之旅。。。
知识点
参考了两位大佬的文章(文末给出)加以提炼,绘制出由浅入深的快速了解Path的路线。
Path介绍
安卓对直线和曲线进行了封装,都封装到了path这个类中,仅仅只调用canvas.drawPath(Path path,Paint paint)就可以绘制路径。本节就主要探讨path的一些方法
一、基本路径绘制
“两点一线”数学中的概念,这句话好像在哪见过? 哈哈想起来了!我们学习canvas绘制直线的时候就说过。只不过那时我们使用的是canvas提供的drawLine绘制的直线。这里就以Path来绘制下体会下Path的强大之处。
1、lineTo
(1) lineTo介绍
public void lineTo(float x, float y)
根据线的终点坐标,绘制一条线
what fuck ?不是两点一线吗? 给了个终点就能画线?很多人初次了解都会有这个疑问的。其实起点坐标是有的,就是上一次操作的结束点。没有上一次操作时,起点默认为原点。
(2)栗子
public class BasicView extends View {
private Paint paint;
float[] lines = new float[]{0, 0, 300, 0, 0, 0, 0, 300};
private Path path;
public BasicView(Context context) {
this(context, null);
}
public BasicView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BasicView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
path = new Path(); //初始化Path
// 1、初始化画笔
paint = new Paint();
paint.setColor(Color.BLUE);
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
paint.setAntiAlias(true);
paint.setStrokeWidth(8);
paint.setStyle(Paint.Style.STROKE);
}
/**
* 这里了进行绘图相关的操作
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(300, 300); //更改画布的坐标原点
paint.setColor(Color.RED);
canvas.drawLines(lines, paint); //画出移动后的坐标系
paint.setColor(Color.GRAY);
path.lineTo(100, 100);
path.lineTo(100, 0);
canvas.drawPath(path,paint);
}
}
这里吧画笔、path、初始化的操作也贴啦出来,下文就不在给出。直接复用或者稍微改动。。。。。
如上:画了两条线(0,0)到(100,100)这条线 、(100,100)到(100,0)这条线。
2、close方法
其实如上代码当你在path.lineTo后面添加path.close后你会发现一个完整的三角形出来啦!!!
close作用:封闭路径,吧起点和终点连接起来。如果起点和终点链接起来后构不成封闭路径则close便失效。
(1)栗子
3、moveTo 和setLastPosition
(1) public void moveTo (float x, float y)
作用:指定下一次操作的起点
影响:影响下一次的绘制,因为moveTo指定了你下一次操作的起点坐标。
栗子:
(2) public void setLastPoint (float dx, float dy)
作用:重置上一次的终点坐标
影响:不仅影响下一次的的绘制,还影响你上一次绘制,这里代表你修改上一次操作的终点。
如上基于(1)中的图案进行修改。
二、path的addXxx
path也封装了相关api方便我们画圆、椭圆、矩形、圆角矩形等等、、、
1、基本几何图形
(1)方法
// 圆形
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)
1、瞅了瞅,这没啥啊?和之前的绘制基本几何形状几乎一样。这回我们轻车路熟,,,,,
2、看了看Path.Direction了解到这是个枚举常量,代表绘制曲线路径的方向(顺时针、逆时针)
(2)功能特别的Path.Direction枚举类
public class Path {
···
···
/**
* Specifies how closed shapes (e.g. rects, ovals) are oriented when they
* are added to a path.
*/
public enum Direction {
/** clockwise*/
CW (0),
/** counter-clockwise */
CCW (1);
···
···
}
}
注释收获:
1、精确的指出图像是如何关闭的,当添加到path时。
2、 CW,即clockwise 表示顺时针关闭
3、CCW 即counter-clockwise 表示逆时针关闭
简单例子
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(300, 300); //更改画布的坐标原点
paint.setColor(Color.RED);
canvas.drawLines(lines, paint); //画出移动后的坐标系
paint.setColor(Color.GRAY);
path.addRect(-200,-200,200,200,Path.Direction.CW);
canvas.drawPath(path,paint);
}
上面的代码我们把CW换为CCW发现 没啥变化哈哈!!!其实这个顺时针逆时针结合setLastPoint就出现效果啦
(3)CW结合setLastPoint
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(300, 300); //更改画布的坐标原点
paint.setColor(Color.RED);
canvas.drawLines(lines, paint); //画出移动后的坐标系
paint.setColor(Color.GRAY);
path.addRect(-200,-200,200,200,Path.Direction.CW);
path.setLastPoint(-300,300);
canvas.drawPath(path,paint);
}
可以看到,我们修改了最后一次的操作点后图象变化啦!!!
原理解析:
我们声明矩形对角线顶点的顺序:
path.addRect(-200,-200,200,200,Path.Direction.CW);
1、其实在前面章节canvas的drawRect学习时我们就了解到:
画矩形时只需要矩形一条对角线的两顶点就可以画出矩形。
2、其实在使用path时原理是这样的(以上代码中声明点顺序为例子):a:path先调用moveTo移动到初始点A(-200,200)
b:再调用lineTo绘制到B(200,-200),接下来依次为C、D。
ps:从对角线起点顺时针绘制
(4)逆时针测试
可见把上面代码改为逆时针时效果就不一样啦!!!
沿着对角线的起点以逆时针角度绘制。
(5)须知:如上我们根据对角线A(-200,200)D(200,200)绘制出了矩形,但是我们可能会以另外一条对角线CD来绘制。这样是绘制不出来图案的。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(300, 300); //更改画布的坐标原点
paint.setColor(Color.RED);
canvas.drawLines(lines, paint); //画出移动后的坐标系
paint.setColor(Color.GRAY);
path.addRect(200,-200,-200,200,Path.Direction.CW);
canvas.drawPath(path,paint);
}
查看源码:
这个对角线顶点定义为左上开始,右下结束。
绘制基本集合图形原理收获:从起始点开始绘制,按照顺时针或者逆时针绘制。
本小节总结啦绘制矩形的其他的我们可以自行测试。
2、添加Path
(1)方法
public void addPath (Path src)
public void addPath (Path src, float dx, float dy)
public void addPath (Path src, Matrix matrix)
1、重载方法1的:吧一个Path对象添加到这个方法。
2、重载方法2的:添加path,这个path在x、y轴上再进行一段位移。
3、重载方法3的:添加path对象之前先进行矩阵变换。
(2)栗子
private Path newPath = new Path();
···
···
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(300, 300); //更改画布的坐标原点
paint.setColor(Color.RED);
canvas.drawLines(lines, paint); //画出移动后的坐标系
paint.setColor(Color.GRAY);
path.addRect(200, -200, -200, 200, Path.Direction.CW); //矩形
newPath.addCircle(0, 0, 100, Path.Direction.CW); //新的path添加一个圆
path.addPath(newPath);
canvas.drawPath(path, paint);
}
3、添加圆弧
(1)方法1
public void addArc (RectF oval, float startAngle, float sweepAngle)
直接添加圆弧到path
(2)方法1
public void arcTo (RectF oval, float startAngle, float sweepAngle)
添加一个圆弧到path,如果圆弧的起点和上次最后一个坐标点不相同,就连接两个点
(3)具备(1)(2)功能的方法
public void arcTo (RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)
boolean forceMoveTo:
1、true 时等价于(2)
2、false 时等价于 (1)
三、path 工具方法
1、isEmpty
判断path对象是否添加了内容,可以吧path理解为集合。对象刚创建时为空。
2、isRect
public boolean isRect (RectF rect)
判断path是否是一个矩形,如果是一个矩形的话,会将矩形的信息存放进参数rect中。
(1)栗子
path.lineTo(0,400);
path.lineTo(400,400);
path.lineTo(400,0);
path.lineTo(0,0);
RectF rect = new RectF();
boolean b = path.isRect(rect);
3、set
public void set (Path src)
给path重新赋值
4、 offset
(1)
public void offset (float dx, float dy)
平移path
(2)
public void offset (float dx, float dy, Path dst)
吧平移的path 存入新的path对象中
四、简答的雷达图实战
五、贝塞尔曲线
参见单独章节