Android PathMeasure

PathMeasure 是针对Path的测量类,它可以测量Path的长度、某点的坐标、正切值等。api中提供了两个构造方法,这里我们来看带参数的构造方法

    public PathMeasure(Path path, boolean forceClosed) {
        // The native implementation does not copy the path, prevent it from being GC'd
        mPath = path;
        native_instance = native_create(path != null ? path.readOnlyNI() : 0,
                                        forceClosed);
    }

path表示需要进行测量的对象,forceClosed表示在测量过程中,是否路径考虑闭合的状况,传递true值表示不论是否调用path.close()方法,都认为是闭合状态。

    public float getLength() {
        return native_getLength(native_instance);
    }

表示获取当前path的长度。

 public boolean getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo) {
        float length = getLength();
        if (startD < 0) {
            startD = 0;
        }
        if (stopD > length) {
            stopD = length;
        }
        if (startD >= stopD) {
            return false;
        }

        return native_getSegment(native_instance, startD, stopD, dst.mutateNI(), startWithMoveTo);
    }

表示获取path中的某一段长度,startD表示起始值,stopD表示测量终点值,dst为测量后的path对象,startWithMoveTo表示是否移动至path起点并连线,看一下示例
Android PathMeasure_第1张图片
红色区域是绘制了两个边长为200的矩形,我们分别对两个红色矩形测量200至600范围的path,上方的红色矩形在测量中startWithMoveTo参数传递了true,下方的则传递了false,可以很明显的观察到传递false时,将path范围为200的点与我们的画布起始点进行了连线,为true时则不会。

public boolean nextContour() {
        return native_nextContour(native_instance);
    }

如果path为多条互不连接的曲线构成,那么在测量过程中,如果想要测量下一个path的相关数据,调用该方法,则会顺沿到下一个path。

    public boolean getPosTan(float distance, float pos[], float tan[]) {
        if (pos != null && pos.length < 2 ||
            tan != null && tan.length < 2) {
            throw new ArrayIndexOutOfBoundsException();
        }
        return native_getPosTan(native_instance, distance, pos, tan);
    }

测量距离path起始点的长度distance,pos、tan都是长度为2的数组,pos[0]表示x坐标,pos[1]表示y坐标,tan[0]是邻边边长,tan[1]是对边边长,通过Math.atan2(tan[1], tan[0])*180.0/Math.PI 可以得到正切角的弧度值。

下面我们做一个简单的示例,效果图如下:
Android PathMeasure_第2张图片
重点在于getPosTan()方法的使用,该效果实际是对纸飞机进行平移和旋转操作,在对圆path的测量过程中,获取每一个路径的坐标以及正切值,坐标就是飞机的平移坐标,而正切值转换为角度值,就是飞机的旋转角度,主要实现onDraw()方法:

 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        canvas.drawLine(0, getHeight() / 2, getWidth(), getHeight() / 2, linePaint);
        canvas.drawLine(getWidth() / 2, 0, getWidth() / 2, getHeight(), linePaint);
        canvas.translate(getWidth() / 2, getHeight() / 2);

        path.reset();
        path.addCircle(0, 0, 200, Path.Direction.CW);
        canvas.drawPath(path, paint);

        PathMeasure measure = new PathMeasure();

        measure.setPath(path, false);

        speed += 0.004;
        if (speed > 1) {
            speed = 0;
        }
        //这里对圆path进行测量
        measure.getPosTan(measure.getLength() * speed, pos, tan);
        //计算当前角度
        double degree = Math.atan2(tan[1], tan[0]) * 180.0 / Math.PI;

        matrix.reset();
        //旋转飞机
        matrix.postRotate((float) degree,bitmap.getWidth()/2,bitmap.getHeight()/2);
        //平移飞机
        matrix.postTranslate(pos[0]-bitmap.getWidth()/2,pos[1]-bitmap.getHeight()/2);
        canvas.drawBitmap(bitmap,matrix,paint);

        invalidate();
    }

这里我们通过speed对象来实时测量measure.getLength() * speed这一段路径值,并实时计算相应的坐标及角度,不断的对纸飞机进行旋转和平移操作即可。

你可能感兴趣的:(Android)