700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Path绘制动态的贝塞尔曲线 PathMeasure来绘制path动画

Path绘制动态的贝塞尔曲线 PathMeasure来绘制path动画

时间:2024-05-25 04:31:13

相关推荐

Path绘制动态的贝塞尔曲线 PathMeasure来绘制path动画

上一篇的波浪曲线是左右重复平移,这次是每一帧绘制一条线,组成上下浮动的曲线,下面是效果图

public WaveView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);paint = new Paint(Paint.ANTI_ALIAS_FLAG);paint.setStrokeWidth(6);paint.setColor(Color.BLUE);paint.setStyle(Paint.Style.STROKE);path = new Path();

@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawCircle(200, 200, 90, paint);path.reset();path.moveTo(waveLength / 2, startY);path.rQuadTo(waveLength / 2, -waveHeight, waveLength, 0);path.rQuadTo(waveLength / 2, waveHeight, waveLength, 0);canvas.drawPath(path, paint);

下面是通过属性动画来改变贝塞尔控制点

protected void startAnimation() {//通过属性动画计算高度final ValueAnimator animator = ValueAnimator.ofInt(-waveHeight, waveHeight);animator.setDuration(4000);animator.setRepeatCount(ValueAnimator.INFINITE);animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {waveHeight = (int) animation.getAnimatedValue();postInvalidateDelayed(1);}});animator.setRepeatMode(ValueAnimator.REVERSE);animator.start();}

path的曲线动画,下面是效果图

//全部代码如下:private PathMeasure pathM;private Bitmap bitmap;private int bitHeight;private int bitWidth;private Rect rect;private Matrix matrix;public WaveView(Context context) {this(context, null);}public WaveView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);paint = new Paint(Paint.ANTI_ALIAS_FLAG);paint.setStrokeWidth(6);paint.setColor(Color.BLUE);paint.setStyle(Paint.Style.STROKE);path = new Path();//来个path计算器pathM = new PathMeasure();bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.icon_music);bitHeight = bitmap.getHeight();bitWidth = bitmap.getWidth();}private Paint paint;//定义画笔private int waveLength = 200;//定义波长度private Path path;//曲线路径private int waveHeight = 120;//定义波的高度private int startY = 500;//起点的Y坐标private static String TAG = "test";private float fraction = 0.0f;private float[] position = new float[2];private float[] tange = new float[2];@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawCircle(200, 200, 90, paint);path.reset();path.moveTo(waveLength / 2, startY);path.rQuadTo(waveLength / 2, -waveHeight, waveLength, 0);path.rQuadTo(waveLength / 2, waveHeight, waveLength, 0);canvas.drawPath(path, paint);pathM.setPath(path, false);float length = pathM.getLength();Log.i(TAG, "WaveView: 长度==" + length);boolean flag = pathM.getPosTan(fraction * length, position, tange);if (flag) {//开始绘制运行轨迹canvas.drawBitmap(bitmap, position[0] - bitWidth, position[1] - bitHeight, paint);}}protected void computePercent() {ValueAnimator animator = ValueAnimator.ofFloat(0, 1.0f);animator.setDuration(4000);animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {fraction = (float) animation.getAnimatedValue();Log.i(TAG, "onAnimationUpdate: 百分比==" + fraction);postInvalidateDelayed(5);}});animator.start();}

上面有点缺陷就是“音乐符号”的运动角度没有设置和调整,调整后的效果如右边所示:

public WaveView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);paint = new Paint(Paint.ANTI_ALIAS_FLAG);paint.setStrokeWidth(6);paint.setColor(Color.BLUE);paint.setStyle(Paint.Style.STROKE);path = new Path();//新增代码。来个path计算器pathM = new PathMeasure();bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.icon_music);bitHeight = bitmap.getHeight();bitWidth = bitmap.getWidth();matrix=new Matrix();}private Paint paint;//定义画笔private int waveLength = 200;//定义波长度private Path path;//曲线路径private int waveHeight = 120;//定义波的高度private int startY = 500;//起点的Y坐标private static String TAG = "test";private float fraction = 0.0f;private float[] position = new float[2];private float[] tange = new float[2];@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawCircle(200, 200, 90, paint);path.reset();path.moveTo(waveLength / 2, startY);path.rQuadTo(waveLength / 2, -waveHeight, waveLength, 0);path.rQuadTo(waveLength / 2, waveHeight, waveLength, 0);canvas.drawPath(path, paint);pathM.setPath(path, false);float length = pathM.getLength();Log.i(TAG, "WaveView: 长度==" + length);boolean flag = pathM.getPosTan(fraction * length, position, tange);if (flag) {//开始绘制运行轨迹// canvas.drawBitmap(bitmap, position[0] - bitWidth, position[1] - bitHeight, paint);matrix.reset();float degree = (float) (Math.atan2(tange[1], tange[0])*180f/Math.PI);matrix.postRotate(degree,bitmap.getWidth()/2,bitmap.getHeight()/2);matrix.postTranslate(position[0]-bitmap.getWidth()/2,position[1]-bitmap.getHeight()/2);canvas.drawBitmap(bitmap,matrix,paint);}}protected void computePercent() {ValueAnimator animator = ValueAnimator.ofFloat(0, 1.0f);animator.setDuration(4000);animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {fraction = (float) animation.getAnimatedValue();Log.i(TAG, "onAnimationUpdate: 百分比==" + fraction);postInvalidateDelayed(5);}});animator.start();}

总结:还有一种比较好的测量 方式,直接返回matrix,这个matrix里面包含了delt x和y,以及tang角度。

boolean flag = pathM.getMatrix(fraction * length, matrix, PathMeasure.POSITION_MATRIX_FLAG | PathMeasure.TANGENT_MATRIX_FLAG);if (flag) {canvas.drawBitmap(bitmap, matrix, paint);}

新测量方式的源码截取和解释如下

/*** Pins distance to 0 <= distance <= getLength(), and then computes the* corresponding matrix. Returns false if there is no path, or a zero-length* path was specified, in which case matrix is unchanged.** @param distance The distance along the associated path* @param matrix Allocated by the caller, this is set to the transformation* associated with the position and tangent at the specified distance* @param flags Specified what aspects should be returned in the matrix.*/public boolean getMatrix(float distance, Matrix matrix, int flags) { return native_getMatrix(native_instance, distance, matrix.native_instance, flags);}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。