android高级动画——贝塞尔曲线

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wode_dream/article/details/57409729

Android高级动画所有代码

简介:贝塞尔曲线是计算机图形学中相当重要的参数曲线。可以用数学公式来描述一段曲线。

用途:1、贝塞尔曲线可以帮助我们在二维平面内用平滑的曲线画出各种图形。

2、同时也可以给动画提供一个平滑的曲线运动路径。

android中我们通过Path可以画出二阶跟三阶贝塞尔曲线。复杂的图形我们可以组合几个二阶和三阶的贝塞尔曲线就可以实现。

这次整理一下沿着二阶贝塞尔曲线运动的例子。下面是一个沿着二阶贝塞尔曲线运动的小球的代码和讲解。


示例代码:

1、总共有4个代码文件activity、view、Evalutor和xml文件。

2、先分析下最重要的view文件:

public class TestMove extends View implements View.OnClickListener
{
    private float mCircleX,mCircleY;    //小球的圆心

    private Path mMovePath;         //这是用来画贝塞尔曲线的
    private Paint mPaintBezier,mPaintCircle;    //设置画贝塞尔曲线和园的画笔

    private float mStartPointX,mStartPointY;    //二阶贝塞尔曲线的起始点
    private float mEndPointX,mEndPointY;        //二阶贝塞尔曲线的终点
    private float mFlagPointX,mFlagPointY;      //二阶贝塞尔曲线的支撑点


    public TestMove(Context context) {
        super(context);
    }

    public TestMove(Context context, AttributeSet attrs) {
        super(context, attrs);

        //初始化画笔
        mPaintBezier=new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaintBezier.setStrokeWidth(8);
        mPaintBezier.setStyle(Paint.Style.STROKE);
        mPaintBezier.setColor(Color.BLUE);

        mPaintCircle=new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaintCircle.setStrokeWidth(8);
        mPaintCircle.setStyle(Paint.Style.FILL_AND_STROKE);
        mPaintCircle.setColor(Color.BLUE);

        setOnClickListener(this);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        /**
         * 系统每一次需要计算大小时都会执行这个方法,比如view改变的时候。所以我们在这里
         * 获得起始点、终点和支撑点
         */
        mStartPointX = w / 4;
        mStartPointY = h / 2 - 200;

        mEndPointX = w * 3 / 4;
        mEndPointY = h / 2 - 200;

        mFlagPointX = w / 2;
        mFlagPointY = h / 2 - 400;

        mCircleX=mStartPointX;
        mCircleY=mStartPointY;

        mMovePath=new Path();

    }

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

        //画圆
        canvas.drawCircle(mCircleX,mCircleY,30,mPaintCircle);

        //给Path设置贝塞尔曲线,然后canvas画
        mMovePath.reset();
        mMovePath.moveTo(mStartPointX,mStartPointY);
        /**
         * quadTo()绘制二阶贝塞尔曲线
         * cubicTo()绘制三阶贝塞尔曲线
         */
        mMovePath.quadTo(mFlagPointX,mFlagPointY,mEndPointX,mEndPointY);
        canvas.drawPath(mMovePath,mPaintBezier);

    }

    @Override
    public void onClick(View v) {
        PointF flagPoint1=new PointF(mFlagPointX,mFlagPointY);

        PointF startPoint=new PointF(mStartPointX,mStartPointY);
        PointF endPoint=new PointF(mEndPointX,mEndPointY);

        /**
         * 在startPoint和endPoint之间运动时返回一个ValueAnimator的值
         * MoveEvalutor在它的文件里详细解释
         */
        ValueAnimator mValueAnimator=ValueAnimator.ofObject(new MoveEvalutor(flagPoint1),
                startPoint,endPoint);
        mValueAnimator.setDuration(4000);
        mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                /**
                 * 把小球的圆心设置到运动点
                 */
                PointF point=(PointF) animation.getAnimatedValue();
                mCircleX=point.x;
                mCircleY=point.y;
                invalidate();
            }
        });
        mValueAnimator.start();
    }
}

3MoveEvalutor.java的代码:

/**
 * Created by zhaofeng on 2017/2/13.
 *
 * Evalutor允许开发者在任意类型上创建动画,以此来执行动画系统不能直接识别的动画类型。
 */

public class MoveEvalutor implements TypeEvaluator<PointF>{

    private PointF mFlagPoint1;

    public MoveEvalutor(PointF flagPoint) {
        mFlagPoint1=flagPoint;
    }
    @Override
    public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
        return CalculateBezierPointForQuadratic(fraction,startValue,mFlagPoint1,endValue);
    }
    /**
     * B(t) = (1 - t)^2 * P0 + 2t * (1 - t) * P1 + t^2 * P2, t ∈ [0,1]
     *计算贝塞尔曲线的运动点,这个代码在网上可以找到,二阶的三阶的。
     * @param t  曲线长度比例
     * @param p0 起始点
     * @param p1 控制点
     * @param p2 终止点
     * @return t对应的点
     */
    public static PointF CalculateBezierPointForQuadratic(float t, PointF p0, PointF p1, PointF p2) {
        PointF point = new PointF();
        float temp = 1 - t;
        point.x = temp * temp * p0.x + 2 * t * temp * p1.x + t * t * p2.x;
        point.y = temp * temp * p0.y + 2 * t * temp * p1.y + t * t * p2.y;
        return point;
    }
}

4、在activity_move_on_bezier.xml,在xml文件中引入view文件。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_move_on_bezier"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.zfeng.bazier.MoveOnBezierActivity">
    <com.zfeng.bazier.view.MoveOnBezierView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>
5、在activity中执行:

public class MoveOnBezierActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_move_on_bezier);
    }
}

以上就是全部的代码,点击view,小球就会沿着二阶贝塞尔曲线运动。


参考资料:

https://developer.android.com/reference/android/view/View.html

https://developer.android.com/reference/android/graphics/Path.html

https://developer.android.com/reference/android/animation/ValueAnimator.html

https://developer.android.com/reference/android/animation/TypeEvaluator.html



猜你喜欢

转载自blog.csdn.net/wode_dream/article/details/57409729