您当前的位置: 首页 >  ui

命运之手

暂无认证

  • 3浏览

    0关注

    747博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

【高级UI】【020】通过PathMeasure测量Path

命运之手 发布时间:2021-11-14 17:54:58 ,浏览量:3

什么是PathMeasure

PathMeasure是用来对Path相关数据进行测量的工具类

它可以测出Path的长度,点位置,切线斜率,判断路径是否闭合,截取子路径等功能

PathMeasure函数接口


	//绑定Path,如果曲线没有闭合,可以通过forceClosed强制闭合
	public void setPath(Path path, boolean forceClosed);
	
	//计算路径总长度
	public float getLength();
	
	//获取路径指定位置的坐标和切线方向
	//这个位置,是通过指定点到起点的路径长度来表示的
	//pos中的值为[x,y],tan中的值为[Δx,Δy]
	boolean getPosTan(float distance, float pos[], float tan[]);
	
	//获取指定位置的坐标和正切
	//可以通过flag指定全部获取,还是只获取其中一个
	//flags = PathMeasure.POSITION_MATRIX_FLAG | PathMeasure.TANGENT_MATRIX_FLAG
	//位置信息存到矩阵中,可用来进行平移变换,正切信息存到矩阵中,可用来进行旋转变换
	boolean getMatrix(float distance, Matrix matrix, int flags);
	
	//截取start-end位置的子路径,存入dst变量
	//start和end是点到路径起点的总距离
	//注意,这个函数是将新的子路径,直接拼接到dst路径上面,它并不会清除dst路径中已有的数据
	//如果需要清除dst路径中的已有数据,需要自己调用reset方法
	//startWithMoveTo=true,表示通过moveTo的方式连接新路径
	//startWithMoveTo=false,表示通过lineTo的方式连接新路径
	public boolean getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo) 
	
	//如果一个路径是不连续的,则它会包含多个子路径
	//getSegment和getLength等,默认是在首个子路径上计算长度和截取部分
	//如果想在其它子路径上操作,则需要调用nextContour,调至下个子路径
	public boolean nextContour()
	
	//判断当前子路径是否闭合
	boolean isClosed();

PathMeasure应用案例

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 核心代码


	package com.android.architecture;
	
	import android.animation.ValueAnimator;
	import android.content.Context;
	import android.graphics.Canvas;
	import android.graphics.Color;
	import android.graphics.Paint;
	import android.graphics.Path;
	import android.graphics.PathMeasure;
	import android.util.AttributeSet;
	import android.view.View;
	import android.view.animation.AccelerateDecelerateInterpolator;
	
	//进度加载动画
	@SuppressWarnings("all")
	public class B extends View {
	
	    Paint paint = new Paint();
	
	    Path srcPath = new Path();
	    Path dstPath = new Path();
	    PathMeasure pathMeasure = new PathMeasure();
	
	    float progress;
	    float length;
	
	    public B(Context context) {
	        this(context, null);
	    }
	
	    public B(Context context, AttributeSet attributeSet) {
	        super(context, attributeSet);
	        init(context, attributeSet);
	
	        //开始进度动画
	        //进度动画有加速减速过程,比我们自己去匀速控制进度更自然
	        ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
	        anim.addUpdateListener(animation -> {
	            progress = (float) animation.getAnimatedValue();
	            invalidate();
	        });
	        anim.setDuration(2000);
	        anim.setRepeatCount(ValueAnimator.INFINITE);
	        anim.setInterpolator(new AccelerateDecelerateInterpolator());
	        anim.start();
	    }
	
	    protected void init(Context context, AttributeSet attributeSet) {
	
	        //关闭硬件加速
	        setLayerType(LAYER_TYPE_SOFTWARE, null);
	
	        //创建画笔
	        paint.setAntiAlias(true);
	        paint.setColor(Color.RED);
	        paint.setStrokeWidth(10);
	        paint.setStyle(Paint.Style.STROKE);
	
	        //完整路径
	        srcPath.addCircle(400, 400, 200, Path.Direction.CCW);
	
	        //计算路径总长度
	        pathMeasure.setPath(srcPath, true);
	        length = pathMeasure.getLength();
	    }
	
	
	    @Override
	    protected void onDraw(Canvas canvas) {
	
	        //画局部弧
	        double arcRatio = 0.5 - Math.abs(0.5 - progress);
	        double stop = length * progress;
	        double start = stop - length * arcRatio;
	        dstPath.reset();
	        pathMeasure.getSegment((float) start, (float) stop, dstPath, true);
	        canvas.drawPath(dstPath, paint);
	    }
	}




	package com.android.architecture;
	
	import android.content.Context;
	import android.graphics.Bitmap;
	import android.graphics.BitmapFactory;
	import android.graphics.Canvas;
	import android.graphics.Color;
	import android.graphics.Matrix;
	import android.graphics.Paint;
	import android.graphics.Path;
	import android.graphics.PathMeasure;
	import android.util.AttributeSet;
	import android.view.View;
	
	//阿童木沿圆形太阳漫游动画
	@SuppressWarnings("all")
	public class A extends View {
	
	    Bitmap bitmap;
	    Paint paint;
	    Matrix matrix = new Matrix();
	
	    float progress = 0;
	
	    public A(Context context) {
	        this(context, null);
	    }
	
	    public A(Context context, AttributeSet attributeSet) {
	        super(context, attributeSet);
	        init(context, attributeSet);
	    }
	
	
	    private void init(Context context, AttributeSet attributeSet) {
	
	        //图片缩小
	        BitmapFactory.Options options = new BitmapFactory.Options();
	        options.inJustDecodeBounds = true;
	        BitmapFactory.decodeResource(context.getResources(), R.drawable.atm, options);
	        options.inSampleSize = options.outWidth / 50;
	        options.inJustDecodeBounds = false;
	        bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.atm, options);
	
	        //创建画笔
	        paint = new Paint();
	        paint.setAntiAlias(true);
	        paint.setColor(Color.RED);
	        paint.setStrokeWidth(5);
	        paint.setStyle(Paint.Style.STROKE);
	    }
	
	
	    @Override
	    protected void onDraw(Canvas canvas) {
	
	        //计算动画进度
	        progress += 0.005;
	        if (progress >= 1)
	            progress = 0;
	
	        //画底色
	        canvas.drawColor(Color.WHITE);
	
	        //从中间开始画
	        canvas.translate(getMeasuredWidth() / 2, getMeasuredHeight() / 2);
	
	        //顺时针画圆
	        Path path = new Path();
	        path.addCircle(0, 0, 200, Path.Direction.CW);
	
	        //获得圆上指定点的位置和正切
	        //这两个属性,可以作为图片的平移距离和旋转角度来使用
	        //Path上点的位置,就是绘图时,图片左上角的位置,点切线的方向,就是图片旋转的方向
	        PathMeasure pathMeasure = new PathMeasure(path, false);
	        float distance = pathMeasure.getLength() * progress;
	        pathMeasure.getMatrix(distance, matrix, PathMeasure.POSITION_MATRIX_FLAG | PathMeasure.TANGENT_MATRIX_FLAG);
	        //动画左下角与圆吻合,因此要先平移一下,调整绘图的起点位置
	        matrix.preTranslate(0, -bitmap.getHeight());
	
	        //画平移旋转后的图像
	        canvas.drawPath(path, paint);
	        canvas.drawBitmap(bitmap, matrix, paint);
	
	        //刷新下一帧
	        postInvalidateDelayed(30);
	    }
	}



	package com.android.architecture;
	
	import android.animation.ValueAnimator;
	import android.content.Context;
	import android.graphics.Bitmap;
	import android.graphics.BitmapFactory;
	import android.graphics.Canvas;
	import android.graphics.Color;
	import android.graphics.Matrix;
	import android.graphics.Paint;
	import android.graphics.Path;
	import android.graphics.PathMeasure;
	import android.util.AttributeSet;
	import android.view.MotionEvent;
	import android.view.View;
	import android.view.animation.LinearInterpolator;
	
	//阿童木沿波浪冲锋
	@SuppressWarnings("all")
	public class C extends View {
	
	    public static final int WAVE_LENGTH = 600;
	
	    Bitmap bitmap;
	    Paint paint = new Paint();
	
	    Path path = new Path();
	    PathMeasure pathMeasure;
	    Matrix matrix = new Matrix();
	
	    ValueAnimator anim;
	
	    float progress;
	    int positive = 1;
	
	    public C(Context context) {
	        this(context, null);
	    }
	
	    public C(Context context, AttributeSet attributeSet) {
	        super(context, attributeSet);
	        init(context, attributeSet);
	    }
	
	    protected void init(Context context, AttributeSet attributeSet) {
	
	        //图片缩小
	        BitmapFactory.Options options = new BitmapFactory.Options();
	        options.inJustDecodeBounds = true;
	        BitmapFactory.decodeResource(context.getResources(), R.drawable.atm, options);
	        options.inSampleSize = options.outWidth / 50;
	        options.inJustDecodeBounds = false;
	        bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.atm, options);
	
	        //创建画笔
	        paint.setAntiAlias(true);
	        paint.setColor(Color.RED);
	        paint.setStrokeWidth(5);
	        paint.setStyle(Paint.Style.STROKE);
	
	        //开始进度动画
	        anim = ValueAnimator.ofFloat(0, 1);
	        anim.setDuration(8000);
	        anim.setRepeatMode(ValueAnimator.REVERSE);
	        anim.setRepeatCount(ValueAnimator.INFINITE);
	        anim.setInterpolator(new LinearInterpolator());
	        anim.addUpdateListener(animation -> {
	            float old = progress;
	            progress = (float) animation.getAnimatedValue();
	            if (progress > old)
	                positive = 1;
	            if (progress             
关注
打赏
1654938663
查看更多评论
0.0686s