前面http://www.jianshu.com/p/35765aa6f7d9 所讲的绘制的图形都是基本的简单图形,如矩形,员,圆弧等。如果对于一些复杂的图形(五角星,心形)的绘制,前面的绘图方法就无能为力了。而使用Path不仅可以绘制简单的图形,还能复制一些复杂的图形。
Google官网上Path的链接为:https://developer.android.google.cn/reference/android/graphics/Path.html
google官网上对path的解释为:
- The Path class encapsulates compound (multiple contour) geometric paths consisting of straight line segments, quadratic curves, and cubic curves. It can be drawn with canvas.drawPath(path, paint), either filled or stroked (based on the paint’s Style), or it can be used for clipping or to draw text on a path.
- 大意是Path类封装了直线段,二次bezier曲线,三次bezier曲线等几何路径,可以通过canvas.drawPath(path, paint)方法画出,画笔的类型可以是filled 或者 stroked,可以用于通过路径裁剪或者绘制文本。
Path的相关方法
作用 | 相关方法 | 备注 |
---|---|---|
移动起点 | moveTo(float x, float y) | Set the beginning of the next contour to the point (x,y). |
设置终点 | setLastPoint(float dx, float dy) | Sets the last point of the path. |
连接直线 | lineTo(float x, float y) | Add a line from the last point to the specified point (x,y). |
闭合路径 | close() | Close the current contour. |
添加内容 | addArc、addCircle、addOval、addPath、addRect、addRoundRect、arcTo | 添加( 圆弧、 圆, 椭圆,路径,矩形, 圆角矩形, ) 到当前Path |
是否为空 | isEmpty() | Returns true if the path is empty (contains no lines or curves) |
是否为矩形 | isRect(RectF rect) | Returns true if the path specifies a rectangle. |
替换路径 | set(Path src) | Replace the contents of this with the contents of src. |
偏移路径 | offset | Offset the path by (dx,dy) |
重置路径 | reset()、rewind() | Clear any lines and curves from the path, making it empty./Rewinds the path: clears any lines and curves from the path but keeps the internal data structure for faster reuse. |
rXxx方法 | rCubicTo、rLineTo、rMoveTo、rQuadTo | 不带r的方法是基于原点的坐标系(偏移量), rXxx方法是基于当前点坐标系(偏移量) |
贝塞尔曲线 | quadTo、cubicT | 分别为二次和三次贝塞尔曲线的方法 |
矩阵操作 | transform | Transform the points in this path by matrix |
填充模式 | setFillType、toggleInverseFillType()、isInverseFillType()、getFillType() | 设置、切换、判断和获取填充模式 |
计算边界 | computeBounds | Compute the bounds of the control points of the path, and write the answer into bounds. |
布尔操作 | op | Set this path to the result of applying the Op to the two specified paths |
lineTo
首先先要说的是lineTo ,lineTo的方法如下:
lineTo(float x, float y)
Add a line from the last point to the specified point (x,y)
在上次的结束点和指定的点之间添加一条line,the last point是上次操作结束的点,如果没有上次结束的点呢,额,那就默认为坐标原点。
现在测试一下:
int mWidth = getWidth();
int mHeight = getHeight();
canvas.translate(mWidth/2,mHeight/2); //坐标移动到屏幕中心
Path path=new Path(); //创建Path
path.lineTo(200,200);
path.lineTo(200,-200);
canvas.drawPath(path,mPaint2); //绘制Path
在例子中,我们调用了两次lineTo,第一次调用时,因为之前没有调用过,所以默认点是坐标原点,第二次调用时,因为上次调用的结束点是(200,200),所以这次lineTo是(200,200)到(200,-200)之间的连线。
moveTo 和 setLastPoint:
moveTo(float x, float y) :Set the beginning of the next contour to the point (x,y).
setLastPoint(float dx, float dy):Sets the last point of the path
这两个方法看起来比较类似,其实是有很大不同的,如下表所示:
方法名 | 简介 | 是否影响之前的操作 | 是否影响之后操作 |
---|---|---|---|
moveTo(float x, float y) | 设置下次Path的起点 | 否 | 是 |
setLastPoint(float dx, float dy) | 设置上次操作最后一个点的位置 | 是 | 是 |
直接上代码:
canvas.translate(mWidth / 2, mHeight / 2);
Path path = new Path();
path.lineTo(200,200);
path.moveTo(200,0);
path.lineTo(200,-200);
canvas.drawPath(path,mPaint2);
moveTo只改变下次操作的起点,在执行完第一次LineTo的时候,本来的默认点位置是(200,200),但是moveTo将其改变成为了(200,0),所以在第二次调用lineTo的时候就是连接(200,0) 到 (200,-200) 之间的直线。
- 下面是setLastPoint
canvas.translate(mWidth/2,mHeight/2);
Path path=new Path();
path.lineTo(200,200);
canvas.drawPoint(200,200,mPaint2);
path.setLastPoint(200,100);
path.lineTo(200,-200);
canvas.drawPath(path,mPaint2);
setLastPoint是重置上一次操作的最后一个点,在执行完第一次的lineTo的时候,最后一个点是(200,200),而setLastPoint更改最后一个点为(200,100),所以在实际执行的时候,第一次的lineTo就不是从原点到(200,200)的连线了,而变成了从原点到C(200,100)之间的连线了。
在执行完第一次lineTo和setLastPoint后,最后一个点的位置是(200,100),所以在第二次调用lineTo的时候就是(200,100) 到 (200,-200) 之间的连线。
close
close():Close the current contour
close方法用于连接当前最后一个点和最初的一个点(如果两个点不重合的话),最终形成一个封闭的图形。
canvas.translate(mWidth/2,mHeight/2);
Path path=new Path();
path.lineTo(200,200); path.lineTo(200,-200);
path.close();
canvas.drawPath(path,mPaint2);
注意:close的作用是封闭路径,与连接当前最后一个点和第一个点并不等价。如果连接了最后一个点和第一个点仍然无法形成封闭图形,则close什么 也不做。
addXXX和arcTo
这次方法主要是在Path中添加基本图形,重点区分addArc与arcTo。
- 添加基本形状
1.添加圆形
addCircle(float x, float y, float radius, Path.Direction dir)
2.添加椭圆
addOval(RectF oval, Path.Direction dir)
addOval(float left, float top, float right, float bottom, Path.Direction dir)
3.添加矩形
addRect(RectF rect, Path.Direction dir)
addRect(float left, float top, float right, float bottom, Path.Direction dir)
4.添加圆角矩形
addRoundRect(RectF rect, float rx, float ry, Path.Direction dir)
addRoundRect(float left, float top, float right, float bottom, float rx, float ry, Path.Direction dir)
可以看到,上述方法都有一个参数, Path.Direction dir,具体是做什么的呢
Direction的意思是 方向,趋势。 点进去看一下会发现Direction是一个枚举(Enum)类型,里面只有两个枚举常量,如下:
类型 | 解释 | 说明 |
---|---|---|
CW | clockwise | 顺时针 |
CCW | counter-clockwise | 逆时针 |
addPath
addPath(Path src) :Add a copy of src to the path
addPath(Path src, float dx, float dy):Add a copy of src to the path, offset by (dx,dy)
addPath(Path src, Matrix matrix):Add a copy of src to the path, transformed by matrix
addPath方法很明了,就是把两个Path合并为一个
第二个方法是将src平移后再合并在一起
第三个方法是将src进行Matrix变换后再合并到一起
canvas.translate(mWidth/2,mHeight/2);
Path path=new Path();
Path src=new Path();
path.addRect(-200,-200,200,200,Path.Direction.CW);
src.addCircle(0,0,100,Path.Direction.CW);
path.addPath(src,0,-200);
canvas.drawPath(path,mPaint2);
addArc与arcTo
addArc(RectF oval, float startAngle, float sweepAngle)— Add the specified arc to the path as a new contour.
addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle)—Add the specified arc to the path as a new contour
arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)—Append the specified arc to the path as a new contour.
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.
arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)—Append the specified arc to the path as a new contour
方法名 | 作用 | 区别 |
---|---|---|
addArc | 添加一个圆弧到path | 直接添加一个圆弧到path |
arcTo | 添加一个圆弧到path | 如果圆弧的起点和上次最后一个坐标点不同,就连接两个点 |
另外,可以看到arcTo方法最后一个参数是个boolean类型的,forceMoveTo,有什么作用呢
forceMoveTo | 含义 |
---|---|
true | 将最后一个点移动到圆弧起点,即不连接最后一个点与圆弧起点 |
false | 不移动,而是连接最后一个点与圆弧起点 |
addArc
canvas.translate(mWidth/2,mHeight/2);
Path path=new Path();
path.lineTo(100,100);
RectF oval=new RectF(0,0,300,300);
path.addArc(oval,0,270);
canvas.drawPath(path,mPaint2);
arcTo
canvas.translate(mWidth/2,mHeight/2);
Path path=new Path();
path.lineTo(100,100);
RectF oval=new RectF(0,0,300,300);
path.arcTo(oval,0,270);
canvas.drawPath(path,mPaint2);
isEmpty、 isRect、isConvex、 set 和 offset
- isEmpty()–Returns true if the path is empty (contains no lines or curves)
主要是判断path是否为空 - isRect(RectF rect):Returns true if the path specifies a rectangle.
判断path是否是一个矩形 - set(Path src):Replace the contents of this with the contents of src
将新的path赋值到就得path - offset(float dx, float dy)
- offset(float dx, float dy, Path dst)
将path进行平移
可以看到第二个方法多了一个dst参数,有什么不同呢
dst状态 | 效果 |
---|---|
dst不为空 | 将当前path平移后的状态存入dst中,不会影响当前path |
dst为空(null) | 平移将作用于当前path,相当于第一种方法 |
canvas.translate(mWidth/2,mHeight/2);
Path path=new Path();
path.addCircle(0,0,100,Path.Direction.CW);
Path dst=new Path();
path.offset(300,0,dst);
canvas.drawPath(path,mPaint2);
path.offset(300,0);
canvas.drawPath(path,mPaint2);
![Paste_Image.png](http://upload-images.jianshu.io/upload_images/3897939-1bde4442ed698893.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300
)
代码下载地址
https://github.com/baojie0327/ViewAndGroup