Api
/*
设置path
path : path对象
forceClosed : 是否闭合(获取长度是需要)
(例如一个半圆,不闭合长度是周长的一般,闭合是周长的一半+直径)
*/
public void setPath(Path path, boolean forceClosed)
/*
获取路径的长度(闭合和不闭合的长度不一样)
如果有两个线段,他们之间不相连,那么长度只是第一个线段的,不是两个线段相加
*/
public float getLength()
/*
是否是闭合
*/
public boolean isClosed()
/*
指定到下一段线段
当有两个线段,他们不相连的时候,通过这个方法,可以指定到下一段线段
*/
public boolean nextContour()
测试代码 :
mPaint.strokeWidth = 10f
mPaint.style = Paint.Style.STROKE
mPath.moveTo(100f, 500f)
mPath.lineTo(800f, 500f)
mPath.moveTo(100f, 800f)
mPath.lineTo(900f, 800f)
mPathMeasure.setPath(mPath, false)
SystemLog.log("length = ${mPathMeasure.length}")
mPathMeasure.nextContour()
SystemLog.log("length = ${mPathMeasure.length}")
System.out: length = 700.0
System.out: length = 800.0
1618297945(1).png
/*
distance: 距离Path起始点的距离,取值范围0 <= distance <= getLength()
pos[]: distance在path上的坐标,即pos[]存的该点的坐标x,y值
tan[]: distance在path上对应坐标点在path上的方向,tan[0]是邻边边长,tan[1]是对边边长。
通过Math.atan2(tan[1], tan[0])*180.0/Math.PI 可以得到正切角的弧度值
*/
public boolean getPosTan(float distance, float pos[], float tan[])
测试代码:
private val mRegion: Region = Region()
private val mPaint: Paint = Paint()
private val mPath: Path = Path()
private val mPathMeasure: PathMeasure = PathMeasure()
private val mPos: FloatArray = FloatArray(2)
private val mTan: FloatArray = FloatArray(2)
private var mDistance: Float = 0f
private var mLength: Float = 0f
private lateinit var mBitmap: Bitmap
private val mMatrix: Matrix = Matrix()
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
mPaint.color = Color.GREEN
mPaint.strokeWidth = 10f
mPaint.style = Paint.Style.STROKE
mPath.addCircle(measuredWidth / 2f, measuredHeight / 2f, 200f, Path.Direction.CW)
mPathMeasure.setPath(mPath, false)
mLength = mPathMeasure.length
mPathMeasure.getPosTan(mDistance, mPos, mTan)
SystemLog.log("resources = $resources")
mBitmap = BitmapFactory.decodeResource(resources, R.drawable.ic_plane)
}
override fun onDraw(canvas: Canvas?) {
canvas?.drawPath(mPath, mPaint)
canvas?.drawBitmap(mBitmap, mMatrix, mPaint)
mPathMeasure.getPosTan(mDistance, mPos, mTan)
mMatrix.reset()
mMatrix.postRotate(
(atan2(mTan[1].toDouble(), mTan[0].toDouble()) * 180.0 / Math.PI).toFloat() + 90,
mBitmap.width / 2f, mBitmap.height / 2f
)
mMatrix.postTranslate(mPos[0] - mBitmap.width / 2, mPos[1] - mBitmap.height / 2)
if (mDistance >= mLength) {
mDistance = 0f
} else {
mDistance += 3
}
invalidate()
}
59052b8dc535cec349c62b95a3c21244[00_00_01--00_00_09].gif
/*
用于得到路径上某一长度的位置以及该位置的正切值的矩阵
distance: 距离 Path 起点的长度,0 <= distance <= getLength
matrix : 根据 falgs 封装好的matrix
flags : 规定哪些内容会存入到matrix中
PathMeasure.POSITION_MATRIX_FLAG(位置)
PathMeasure.ANGENT_MATRIX_FLAG(正切)
*/
public boolean getMatrix(float distance, Matrix matrix, int flags)
在 getPosTan()方法中,我们通过数组获取其中的数据,最后还是封装到了matrix 中
这个方法是直接封装到 matrix 中,不需要我们自己封装
同时选中flags : PathMeasure.POSITION_MATRIX_FLAG | PathMeasure.ANGENT_MATRIX_FLAG
/*
截取path路径上的一段数据
startD : 开始位置(startD>=0&&startD<=length)
stopD: 开始位置(stopD>startD &&stopD<=length)
dst:一个新的path路径,截取后的数据存储在这里
注意: 截取后的数据是添加到path中,不是替换(覆盖),如果你多次的截取,数据会不断的添加
startWithMoveTo : 起点是否使用moveTo,
true : 起点还是原来path的起点
false : 会将截取出来的 Path 片段的起始点移动到 dst 的最后一个点,以保证 dst 的连续性
*/
public boolean getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo)
测试代码:
private val mPaint: Paint = Paint()
private val mPathCircle: Path = Path()
private val mPathLine: Path = Path()
private val mPathMeasureCircle: PathMeasure = PathMeasure()
private val mPathMeasureLine: PathMeasure = PathMeasure()
private var mStart: Float = 0f
private var mLengthCircle: Float = 0f
private var mLengthLine: Float = 0f
private var mState: Boolean = true
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
mPaint.strokeWidth = 10f
mPaint.style = Paint.Style.STROKE
mPathCircle.addCircle(w / 2f, h / 2f, 200f, Path.Direction.CW)
mPathLine.moveTo(w / 2f + 200f, h / 2f)
mPathLine.lineTo(w / 2f + 200f + 200f, h / 2f)
mPathMeasureCircle.setPath(mPathCircle, false)
mPathMeasureLine.setPath(mPathLine, false)
mLengthCircle = mPathMeasureCircle.length
mLengthLine = mPathMeasureLine.length
}
override fun onDraw(canvas: Canvas?) {
canvas?.drawPath(mPathCircle, mPaint)
canvas?.drawPath(mPathLine, mPaint)
if (mState) {
if (mStart < mLengthCircle) {
mPathCircle.reset()
mPathMeasureCircle.getSegment(mStart, mLengthCircle, mPathCircle, true)
mStart += 4
} else if (mStart > mLengthCircle && mStart <= (mLengthCircle + mLengthLine)) {
mPathLine.reset()
mPathMeasureLine.getSegment(mStart - mLengthCircle, mLengthLine, mPathLine, true)
mStart += 4
} else {
mState = false
}
} else {
if (mStart >= mLengthCircle) {
mPathLine.reset()
mPathMeasureLine.getSegment(mStart - mLengthCircle, mLengthLine, mPathLine, true)
mStart -= 4
} else if (mStart < mLengthCircle && mStart >= 0) {
mPathCircle.reset()
mPathMeasureCircle.getSegment(mStart, mLengthCircle, mPathCircle, true)
mStart -= 4
} else {
mState = true
}
}
invalidate()
}
a25e050fa91ca61aa6bc1fc6888fbfea[00_00_01--00_00_21].gif
网友评论