Path
Posted winfredzen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Path相关的知识,希望对你有一定的参考价值。
Path
内容来自:
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 | 矩阵变换 |
方法说明
lineTo
lineTo绘制直线,起点是上次调用的最后一个点的坐标,如果没有,则为坐标原点
canvas.translate(mWidth / 2, mHeight / 2); // 移动坐标系到屏幕中心(宽高数据在onSizeChanged中获取)
Path path = new Path(); // 创建Path
path.lineTo(200, 200); // lineTo
path.lineTo(200,0);
canvas.drawPath(path, mPaint); // 绘制Path
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 | clockwise | 顺时针 |
CCW | counter-clockwise | 逆时针 |
合并path
// 第二类(Path)
// path
//合并path
public void addPath (Path src)
//将src进行了位移之后再添加进当前path中
public void addPath (Path src, float dx, float dy)
//将src添加到当前path之前先使用Matrix进行变换
public void addPath (Path src, Matrix matrix)
如下的例子:
canvas.translate(mWidth / 2, mHeight / 2); // 移动坐标系到屏幕中心
canvas.scale(1,-1); // <-- 注意 翻转y坐标轴
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);
mPaint.setColor(Color.BLACK); // 绘制合并后的路径
canvas.drawPath(path,mPaint);
addArc与arcTo
// 第三类(addArc与arcTo)
// addArc 直接添加一个圆弧到path中
public void addArc (RectF oval, float startAngle, float sweepAngle)
// arcTo 添加一个圆弧到path,如果圆弧的起点和上次最后一个坐标点不相同,就连接两个点
public void arcTo (RectF oval, float startAngle, float sweepAngle)
public void arcTo (RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)
oval
- 圆弧的外切矩形startAngle
- 开始角度sweepAngle
- 扫过角度(-360 <= sweepAngle <360)forceMoveTo
- 是否强制使用MoveTo- true - 将最后一个点移动到圆弧起点,即不连接最后一个点与圆弧起点
- false - 不移动,而是连接最后一个点与圆弧起点
canvas.translate(mWidth / 2, mHeight / 2); // 移动坐标系到屏幕中心
canvas.scale(1,-1); // <-- 注意 翻转y坐标轴
Path path = new Path();
path.lineTo(100,100);
RectF oval = new RectF(0,0,300,300);
path.addArc(oval,0,270);
// path.arcTo(oval,0,270,true); // <-- 和上面一句作用等价
canvas.drawPath(path,mPaint);
canvas.translate(mWidth / 2, mHeight / 2); // 移动坐标系到屏幕中心
canvas.scale(1,-1); // <-- 注意 翻转y坐标轴
Path path = new Path();
path.lineTo(100,100);
RectF oval = new RectF(0,0,300,300);
path.arcTo(oval,0,270);
// path.arcTo(oval,0,270,false); // <-- 和上面一句作用等价
canvas.drawPath(path,mPaint);
贝塞尔曲线
二阶曲线
Path path = new Path();
path.moveTo(start.x,start.y);
path.quadTo(control.x,control.y,end.x,end.y);
canvas.drawPath(path, mPaint);
三阶曲线
Path path = new Path();
path.moveTo(start.x, start.y);
path.cubicTo(control1.x, control1.y, control2.x,control2.y, end.x, end.y);
canvas.drawPath(path, mPaint);
其它
内容来自:安卓自定义View进阶-Path之完结篇
rXxx方法
rXxx方法的坐标使用的是相对位置(基于当前点的位移),而之前方法的坐标是绝对位置(基于当前坐标系的坐标)。
android中的填充模式
模式 | 简介 |
---|---|
EVEN_ODD | 奇偶规则 |
INVERSE_EVEN_ODD | 反奇偶规则 |
WINDING | 非零环绕数规则 |
INVERSE_WINDING | 反非零环绕数规则 |
Inverse 和含义是“相反,对立”,说明反奇偶规则刚好与奇偶规则相反,例如对于一个矩形而言,使用奇偶规则会填充矩形内部,而使用反奇偶规则会填充矩形外部
Android与填充模式相关的方法
方法 | 作用 |
---|---|
setFillType | 设置填充规则 |
getFillType | 获取当前填充规则 |
isInverseFillType | 判断是否是反向(INVERSE)规则 |
toggleInverseFillType | 切换填充规则(即原有规则与反向规则之间相互切换) |
如下的例子,内外2个矩形,先使用EVEN_ODD
填充规则
mPaint.setStyle(Paint.Style.FILL); // 设置画布模式为填充
mPaint.setColor(Color.RED);
canvas.translate(mWidth / 2, mHeight / 2); // 移动画布(坐标系)
Path outerPath = new Path(); // 创建Path
outerPath.addRect(-400, -400, 400, 400, Path.Direction.CW); // 给Path中添加一个矩形
outerPath.setFillType(Path.FillType.EVEN_ODD); // 设置Path填充模式为 奇偶规则
//outerPath.setFillType(Path.FillType.INVERSE_EVEN_ODD); // 反奇偶规则
Path innerPath = new Path();
innerPath.addRect(-200,-200,200,200, Path.Direction.CW); // 给Path中添加一个矩形
//合并path
outerPath.addPath(innerPath);
canvas.drawPath(outerPath, mPaint);
效果为:
填充规则为反奇偶填充规则INVERSE_EVEN_ODD
,效果为:
当内外矩形都为顺时针,使用非零环绕规则WINDING
当内外矩形都为顺时针,使用反非零环绕规则INVERSE_WINDING
当内矩形为逆时针,外矩形为顺时针,使用非零环绕规则WINDING
当内矩形为逆时针,外矩形为顺时针,使用反非零环绕规则INVERSE_WINDING
布尔操作(API19)
逻辑名称 | 类比 | 说明 | 示意图 |
---|---|---|---|
DIFFERENCE | 差集 | Path1中减去Path2后剩下的部分 | |
REVERSE_DIFFERENCE | 差集 | Path2中减去Path1后剩下的部分 | |
INTERSECT | 交集 | Path1与Path2相交的部分 | |
UNION | 并集 | 包含全部Path1和Path2 | |
XOR | 异或 | 包含Path1与Path2但不包括两者相交的部分 |
如下的例子:
mPaint.setStyle(Paint.Style.FILL);
canvas.translate(mWidth / 2, mHeight / 2);
Path path1 = new Path();
Path path2 = new Path();
Path path3 = new Path();
Path path4 = new Path();
path1.addCircle(0, 0, 200, Path.Direction.CW);
path2.addRect(0, -200, 200, 200, Path.Direction.CW);
path3.addCircle(0, -100, 100, Path.Direction.CW);
path4.addCircle(0, 100, 100, Path.Direction.CCW);
if (Build.VERSION.SDK_INT >= 19)
path1.op(path2, Path.Op.DIFFERENCE);
path1.op(path3, Path.Op.UNION);
path1.op(path4, Path.Op.DIFFERENCE);
canvas.drawPath(path1, mPaint);
计算边界
这个方法主要作用是计算Path所占用的空间以及所在位置,方法如下:
void computeBounds (RectF bounds, boolean exact)
以上是关于Path的主要内容,如果未能解决你的问题,请参考以下文章
HDU 1087 [Super Jumping! Jumping! Jumping!]动态规划