1.2.6基于PathMeasure分析Path测量问题
1.概念:
pathMeasure: 路径测量,一个用来测量path的工具类
2.常用api:
常用api如path长度的测量,path的跳转,path片段的获取等
(1)void setPath(Path path,boolean forceClosed);关联一个Path
绘制横竖两条线,然后将画布的中心坐标平移到这个两条线的交点,也就是这个交点,就是画布的(0,0)点。
显示效果如下:
A.当setPath中的第二个参数forceClosed=true时候
显示结果:
打印结果:
显示结果为路径闭合的周长
B.当setPath中的第二个参数forceClosed=false时候
我们讲上面的setPath中的第二个参数设置为false,ui显示效果如上
打印结果:
显示结果为路径未闭合的周长
注意:
//如果Path进行了调整,需要重新调用setPath方法进行关联
path.lineTo(200, -200);
Log.e("TAG", "onDraw:PathMeasure(path, false) "+ pathMeasure1.getLength())
pathMeasure1.setPath(path, false);
Log.e("TAG", "onDraw:PathMeasure(path, false) "+ pathMeasure1.getLength());
`(2)boolean isClosed();是否闭合
(3)float getLength();//获取Path的长度
(4)boolean nextContour();跳转到下一个轮廓
源码依次给Path添加一个矩形和一个椭圆(图上实际是一个圆形)
手机ui效果打印参数结果如下:
打印结果结果分析:
1.第一打印的是矩形的周长,第二次打印的是圆的周长(2*pi*r)
2.为啥不调用nextContour()只是打印出了第一个数据(矩形的数据)?
答:打印的顺序和path的添加顺序有关,先添加矩形,所以就会打印矩形的周长。
(5)boolean getSegment(float startD,float stopD,Path dst,boolean startWithMoveTo);截取Path的片段
参数值:
startD :表示开始截取位置距离path起点的长度,取值范围(0,,getLength)
stopD:表示结束截取位置的距离path起点的长度,取值范围(0..getLength)
startWithMoveTo:表示起始点是否使用MoveTo进行移动,用于保证截取的path的第一个点位置不变
返回值:
true:截取成功,false截取失败,会将结果存放在dst中
测试使用如下:
path添加一个矩形,然后从从距离path起点为200的地方开始截取,应为矩形为顺时针绘制的,所以顺着这个方向,截取长度1000.显示的效果如上图
补充:如果将getSegment的最后一个参数设置为false,显示效果如下:
补充:
1.这里主要是startWithMoveTo的取值,
true 表示保证截取出来的path片段保持原状
false 会将截取出来的path片段的起点移动到dst的最后一个点以保证dst的连续性,主要就是少了一步moveTo的步骤{核心原理}
2.当startWithMoveTo为false时,起始点是dst的最后一个点,getSegment会根据startD的值去判断dst与path的连接点,也就是超过startD的第一个点(这里的点指的是lineTo的点或者Rect的顶点等),然后截取到stopD。
(6)boolean getPosTan(float distance,float[]pos,float[] tan);获取指定长度位置的坐标以及该点的切线值
参数:distance:表示距离path起点的长度。取值范围:0到Path长度之间
pos:长度为2的float数组,里面存放的是当前点在画布上的位置,分别表示x坐标和y坐标
tan:长度为2的float数组,表示的是当前点在曲线上的方向,通过它能够获取到切线方向与X轴的一个夹角
返回值:
true返回成功。
false返回失败。
测试使用:
手机显示ui
distance=0.即距离path起点我位置为0 也就是左边为(200,0)的位置
打印结果如下:
结果分析:1.有上面可以知道pos[0]表示当前点在画布的x坐标,pos[1]表示当前点在画布的y坐标
2.tan表示的是当前点在曲线上的方向,需要找到当前点的切线,tan[0]表示切线与x轴的夹角在单位圆中邻边的长度,
tan[1]表示的切线与x轴的夹角在单位圆中对边的长度
发现切线与x轴夹角为90度,接下来我们需要知道,这个夹角在单位圆中的他的邻边和对边是多少。我们看下图:
如上图,我们发现交为30的邻边为OA,对边长为AB.
当角度为90度的时候,邻边长变为了0,而对边长变成了1
那么也就应证了我们 的打印的结果 。
扩展:
如果我们想获取path中其他位置的tan结果,我们以位置为getLength*7/8点为例演示如下:
找到当前位置的切线
发现与X轴的夹角为45度。我们看上面的单位圆。45度对应的邻边为根号2/2, 对边也是根号2/2,
查看打印结果如下:
我们可以基于这个知识点来实现一个小案例:
效果是箭头不停的在圆环上转。
源码链接:githhub
(7)boolean getMatrix(float distance,Matrix matrix,int flags);获取指定长度位置的矩阵
参数:
distance:距离path起点的长度,范围是0到getLength(path的长度)之间
matrix:将信息存放在Matrix中
flags:指定存放信息的类型
值有两个:
(1)POSITION_MATRIX_FLAG:表示的是位置信息
(2) TANGENT_MATRIX_FLAG:表示当前点在曲线上的方向
返回值:
true:返回成功
false:返回失败
使用案例在上面github源码,再次就不在赘述了。
疑问:
1. Matrix中preTranslate和posTranslate的区别
2.Matrix中postRotate的用法