What is PathMeasures

As the name suggests, PathMeasure is a class that measures Path

The constructor

The constructor Methods described
PathMeasure() Create an empty PathMeasure object.
PathMeasure(Path path, boolean forceClosed) Create a PathMeasure object associated with the specified path object (already created and specified).

Public methods

The return value Method names
float getLength()
boolean getMatrix(float distance, Matrix matrix, int flags)
boolean getPosTan(float distance, float[] pos, float[] tan)
boolean getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo)
boolean isClosed()
boolean nextContour()
void setPath(Path path, boolean forceClosed)

Next, introduce the above methods respectively


1. Constructor

Parameterless constructor:
PathMeasure()
Copy the code

To create an empty PathMeasure that can be used to measure the path length, or to find the location and tangent of the path, call setPath. Once the Path is associated with the measurement object and the Path is changed, the setPath method needs to be called again.

Has parameter constructors
PathMeasure(Path path, boolean forceClosed)
Copy the code

Create a PathMeasure object associated with the specified path object. The measurement object can now return the length of the path as well as the position and tangent at any point along the path. As above, once the Path is associated with the measurement object and the Path is changed, the setPath method needs to be called again. ForceClosed: If true, this path is also considered “closed”.

ForceClosed does not affect the state of the Path itself. But it will affect the measurement results.

Here’s an example:

    canvas.translate(mWidth/2,mHeight/2);

    Path path = new Path();
    path.lineTo(0.200);
    path.lineTo(200.200);
    path.lineTo(200.0);
    PathMeasure measure1 = new PathMeasure(path,false);
    PathMeasure measure2 = new PathMeasure(path,true);

    Log.e("TAG"."forceClosed=false---->"+measure1.getLength());
    Log.e("TAG"."forceClosed=true----->"+measure2.getLength());
    canvas.drawPath(path,mDeafultPaint);
Copy the code

The log is as follows:

E/TAG: forceClosed = false -- -- -- - > 600.0 E/TAG: forceClosed = true -- -- -- -- -- > 800.0Copy the code

The drawing looks like this:

2. Public methods

getLength

Returns the total length of the current Path; If there is no path associated with this measure object, 0 is returned.

isClosed

Returns true if the current Path is close ().

setPath

Path is associated with PathMeasure. Mainly talk about the following methods:

nextContour
public boolean nextContour(a)
Copy the code

Get the next contour in the path, if there is a next contour, return true, and the PathMeasure cuts to the next contour data; Return false if there is no next contour. I understand once moveTo adds a silhouette.

getSegment
public booleanGetSegment (floatStartD,floatStopD, Path DST,booleanStartWithMoveTo)Copy the code

Given the distance between the start and finish, return to the middle section. Return false if the segment length is zero, true otherwise. StartD and stopD fixed value range (0,getLength()). If startD> = stopD, return false (and leave DST unchanged). If startWithMoveTo is true, it begins with moveTo.

parameter role
startD Distance from the start of the Path
stopD End Distance between the interception position and the start of the Path
dst The intercepted Path is added to DST
startWithMoveTo Whether the starting point is moveTo enabled

StartD and stopD ranges from 0 <= startD < stopD <= getLength startWithMoveTo: Whether the first point of the intercepted fragment remains unchanged.

Set to true: Keep the captured fragment unchanged and add it to the DST path. Set to false: The start point of the captured fragment is moved to the last point in the DST path, keeping the DST path continuous

For example: startWithMoveTo is flase

canvas.translate(width/2,height/2);
Path mPath = new Path();
Path mDst = new Path();
PathMeasure mPathMeasure = new PathMeasure();
// Draw a circle with radius 400px clockwise
mPath.addCircle(0.0.400, Path.Direction.CW);
mPathMeasure.setPath(mPath, false);

/ / draw a straight line
mDst.moveTo(110.0);
mDst.lineTo(200.300);

// Cut the arc from 0.25 to 0.5 and place it in DST
mPathMeasure.getSegment(mPathMeasure.getLength() * 0.25 f,
                mPathMeasure.getLength() * 0.5 f,
                mDst,
                false);

canvas.drawPath(mDst, paint);
Copy the code

The renderings are as follows:

StartWithMoveTo: True

getPosTan
public boolean getPosTan(floatdistancefloat pos[], float tan[]) 
Copy the code
parameter role
distance That is, the distance between the desired measurement point and the current path start position
pos Pos [0] is the x coordinate, and pos[1] is the Y coordinate
tan The sine and cosine of the measurement point, tan[0] is cosine, that is, cosine or x-coordinate of the unit circle; Tan [1] is sin, which is the sine value or y coordinate of the unit circle;

Distance value range: 0<=distance<=getLength() A(x,y) origin is O,cos = OA/OB,sin = OA/AB

getMatrix
public boolean getMatrix(float distance, Matrix matrix, int flags)
Copy the code
parameter role
distance That is, the distance between the desired measurement point and the current path start position
matrix According to matrix encapsulated by Falgs
flags Specify what content is stored in the matrix

Flags can be POSITION_MATRIX_FLAG or ANGENT_MATRIX_FLAG

In fact, this method is equivalent to the process of getPosTan packaging matrix, which is done by getMatrix for us. We can directly obtain a package to matrix.

In actual combat

Loading animation (1)

rendering

The getSegment method of PathMeasure is mainly used to intercept the path and draw the animation

Train of thought

1. Outline a clockwise hollow circle and generate a pathMeasure object

// Draw a hollow circle
path.addCircle(width / 2, height / 2, radius, Path.Direction.CW);
// Generate pathMeasure objects
pathMeasure.setPath(path, true);
Copy the code

2. Truncated start and end values

stop = mAnimatorValue * mLength;
start = (float) (stop - ((0.5 - Math.abs(mAnimatorValue - 0.5)) * mLength));
Copy the code

The value of mAnimatorValue is (0,1). When mAnimatorValue is 0 or 1, the two values are the same.

3. Intercept a path and draw a path

pathMeasure.getSegment(start, stop, dst, true);
canvas.drawPath(dst, paint);
Copy the code

Useful remember to point a little star


Loading animation (2)

rendering

Train of thought

GetPosTan is mainly used to obtain the coordinates and sines and cosines of the measuring point, and control the method and position of the arrow 1. Draw a clockwise hollow circle and then generate a pathMeasure object

// Draw a hollow circle
path.addCircle(width / 2, height / 2, radius, Path.Direction.CW);
// Generate pathMeasure objects
pathMeasure.setPath(path, true);
Copy the code

2. Obtain the measured coordinates and sines and cosines of the drawing point, and calculate the rotation Angle of the arrow according to tan[0] and Tan [1].

measure.getPosTan(measure.getLength() * mAnimatorValue, pos, tan);
float angle = (float) (Math.atan2(tan[1], tan[0]) * 180 / Math.PI);
Copy the code

The value of mAnimatorValue is (0,1). When mAnimatorValue is 0 or 1, the two values are the same. Angle calculation method to find their own mathematical knowledge.

3. Rotate and translate bitmap with Matrix

mMatrix.postRotate(angle,mBitmap.getWidth()/2,mBitmap.getHeight()/2);
mMatrix.postTranslate(pos[0] - mBitmap.getWidth() / 2,pos[1] - mBitmap.getHeight() / 2);
Copy the code

4. Draw the bitmap

canvas.drawBitmap(mBitmap,mMatrix,mPaint);
Copy the code

Useful remember to point a little star


Address of previous articles

Android animation – Fake bouquet live loading animation

Android animation – copy 58 city loading animation

Android animation – Copy tiktok loading animation