|
| 1 | +# PathMeasure |
| 2 | + |
| 3 | +PathMeasure是一个测量Path的路径的一个方法,我们今天的demo就是要做这样一个小东西,它会反复测量,运动的路径,并且沿着路径运行。 |
| 4 | + |
| 5 | +效果图: |
| 6 | + |
| 7 | + |
| 8 | + |
| 9 | +实现的具体思路,就是,采用一个循环,反复的调用画图的方法,然后每当满一周之后,清零,再重新开始,为什么能沿着切线运动呢,是调用了一个参数,动态测量这个tan值。 |
| 10 | + |
| 11 | +代码: |
| 12 | + |
| 13 | +``` |
| 14 | +public class CustomView extends View { |
| 15 | +
|
| 16 | + private float currentValue = 0; // 用于纪录当前的位置,取值范围[0,1]映射Path的整个长度 |
| 17 | +
|
| 18 | + private float[] pos; // 当前点的实际位置 |
| 19 | + private float[] tan; // 当前点的tangent值,用于计算图片所需旋转的角度 |
| 20 | + private Bitmap mBitmap; // 箭头图片 |
| 21 | + private Matrix mMatrix; // 矩阵,用于对图片进行一些操作 |
| 22 | +
|
| 23 | + private Paint mPaint; |
| 24 | +
|
| 25 | + private int mViewWidth; |
| 26 | + private int mViewHeight; |
| 27 | +
|
| 28 | + public CustomView(Context context) { |
| 29 | + this(context, null); |
| 30 | + } |
| 31 | +
|
| 32 | + public CustomView(Context context, @Nullable AttributeSet attrs) { |
| 33 | + super(context, attrs); |
| 34 | + init(context); |
| 35 | + mPaint = new Paint(); |
| 36 | + mPaint.setColor(Color.BLACK); |
| 37 | + mPaint.setStrokeWidth(8); |
| 38 | + mPaint.setStyle(Paint.Style.STROKE); |
| 39 | + mPaint.setTextSize(60); |
| 40 | +
|
| 41 | +
|
| 42 | + } |
| 43 | +
|
| 44 | + private void init(Context context) { |
| 45 | + pos = new float[2]; |
| 46 | + tan = new float[2]; |
| 47 | + BitmapFactory.Options options = new BitmapFactory.Options(); |
| 48 | + options.inSampleSize = 15; // 缩放图片 |
| 49 | + mBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.arrowhead, options); |
| 50 | + mMatrix = new Matrix(); |
| 51 | + } |
| 52 | +
|
| 53 | +
|
| 54 | + @Override |
| 55 | + protected void onSizeChanged(int w, int h, int oldw, int oldh) { |
| 56 | + super.onSizeChanged(w, h, oldw, oldh); |
| 57 | + mViewHeight = h; |
| 58 | + mViewWidth = w; |
| 59 | +
|
| 60 | + } |
| 61 | +
|
| 62 | + @Override |
| 63 | + protected void onDraw(Canvas canvas) { |
| 64 | + super.onDraw(canvas); |
| 65 | + canvas.translate(mViewWidth / 2, mViewHeight / 2); // 平移坐标系 |
| 66 | +
|
| 67 | + Path path = new Path(); // 创建 Path |
| 68 | +
|
| 69 | + path.addCircle(0, 0, 200, Path.Direction.CW); // 添加一个圆形 |
| 70 | +
|
| 71 | + PathMeasure measure = new PathMeasure(path, false); // 创建 PathMeasure |
| 72 | +
|
| 73 | + currentValue += 0.005; // 计算当前的位置在总长度上的比例[0,1] |
| 74 | + if (currentValue >= 1) { |
| 75 | + currentValue = 0; |
| 76 | + } |
| 77 | +
|
| 78 | + measure.getPosTan(measure.getLength() * currentValue, pos, tan); // 获取当前位置的坐标以及趋势 |
| 79 | +
|
| 80 | + mMatrix.reset(); // 重置Matrix |
| 81 | + float degrees = (float) (Math.atan2(tan[1], tan[0]) * 180.0 / Math.PI); // 计算图片旋转角度 |
| 82 | +
|
| 83 | + mMatrix.postRotate(degrees, mBitmap.getWidth() / 2, mBitmap.getHeight() / 2); // 旋转图片 |
| 84 | + mMatrix.postTranslate(pos[0] - mBitmap.getWidth() / 2, pos[1] - mBitmap.getHeight() / 2); // 将图片绘制中心调整到与当前点重合 |
| 85 | +
|
| 86 | + canvas.drawPath(path, mPaint); // 绘制 Path |
| 87 | + canvas.drawBitmap(mBitmap, mMatrix, mPaint); // 绘制箭头 |
| 88 | +
|
| 89 | + invalidate(); |
| 90 | + } |
| 91 | +
|
| 92 | +} |
| 93 | +
|
| 94 | +``` |
| 95 | + |
| 96 | +代码地址:https://github.com/linsir6/mCustomView/tree/master/TestPathMeasure |
0 commit comments