android高階動畫——貝塞爾曲線
阿新 • • 發佈:2019-02-12
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();
}
}
3、MoveEvalutor.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,小球就會沿著二階貝塞爾曲線運動。
參考資料: