天天看點

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

貝塞爾曲線介紹

貝塞爾曲線(Bézier curve),又稱貝茲曲線或貝濟埃曲線,是應用于二維圖形應用程式的數學曲線。

貝塞爾曲線于1962,由法國工程師皮埃爾·貝塞爾(Pierre Bézier)所廣泛發表,他運用貝塞爾曲線來為汽車的主體進行設計。貝塞爾曲線最初由Paul de Casteljau于1959年運用de Casteljau演算法開發,以穩定數值的方法求出貝茲曲線。

貝塞爾曲線為計算機矢量圖形學奠定了基礎。它的主要意義在于無論是直線或曲線都能在數學上予以描述。

貝塞爾曲線是從起始點P0開始,在控制點的控制下,根據t值的變化而變化,最終到達終點PN之後的路徑,改變控制點的位置會影響最後曲線的形狀,其中t的值為0~1,可以把t當作百分比來了解。

貝塞爾曲線公式推導

一階貝塞爾曲線

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

圖中紅色的線就是一階貝塞爾曲線。

一階貝塞爾曲線最開始隻有開始點P0和結束點P1,沒有控制點,是以是一條直線

紅色的線由點P2動态移動得來,P2跟随着t的變化(從0過渡到1)而變化。我把P2這樣的點成為貝塞爾曲線點

P2變化的規則是   線P0P2 =  線P0P1 * t ,這是線P0P2長度的計算結果,但是點P2的位置是P0的位置加上線P0P2長度才對。

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線
貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線
貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線
貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線
貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

将P2替換成函數B(t)來表達得出,一階貝塞爾曲線一般公式是:

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

二階貝塞爾曲線

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

圖中紅色的曲線既是二階貝塞爾曲線的一種

它的繪制過程有 P0 ~ P5  6個點參與,

最原始的點有三個 P0 ~ P2,P0是開始點,P2是結束點,P1是控制點

P3 ~ P5是P0 ~ P2根據t的變化動态生成的點。

P3 是 P0,P1兩個點的一階貝塞爾曲線點

P4 是 P1,P2兩個點的一階貝塞爾曲線點

P5 是 P3,P4兩個點的一階貝塞爾曲線點

在繪制過程中有三個層的變化過程,第一層,也是最外層的黑色線段,是由初始的點P0,P1,P2按照順序依次連接配接而成,然後在第一層的基礎上,分别取第一層的兩點之間的一階貝塞爾曲線點,進而生成了第二層的兩個點P3,P4,也就是綠色的線段,然後再取第二層的兩個點的一階貝塞爾曲線點,生成了最後的貝塞爾曲線的點P5,最後繪制整個P5的運動軌迹即可得到P0,P1,P2這三個點的二階貝塞爾曲線。

P5是最終的貝塞爾曲線點,它是P3,P4的一階貝塞爾曲線,帶入一階貝塞爾曲線公式,可得

P5 = (1-t)P3 + t*P4

同理P3 = (1-t)P0 + t*P1     P4 = (1-t)P1 +t*P2

将P3,P4的等式代入導P5的計算式中可得

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線
貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

           --->先替換P3

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

     --->然後替換P4

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

  --->展開等式

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

将P5用函數B(t)代替可得二階貝塞爾曲線通用公式

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

三階貝塞爾曲線

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

圖中紅色的曲線就是三階貝塞爾曲線的一種

共有10個點參與繪制,第一層黑色線段 P0-P1-P2-P3,第一層時原始給出的點,後面的點都是根據第一層生成的,第二層綠色線段P4-P5-P6,第三層藍色線段P7-P8,最後一層紅色曲線是P9動态劃過的軌迹,也就是貝塞爾曲線。

在随着t逐漸變化的過程中,除了最外層的點,每個點與它所關聯的點相差了幾層,那這個點就是它所關聯的點幾階貝塞爾曲線,所謂的”關聯“就是,這個點所在的線段,以及所線上段的點所在的線段,以此類推。例如P7與P4、P5這兩個點相差一層,是他們的一階貝塞爾曲線,與P0、P1、P2這三個點相差兩層,是他們的二階貝塞爾曲線。這個規律适用于更高階的貝塞爾曲線。貝塞爾曲線是逐層取一階貝塞爾曲線計算而得。

三階貝塞爾曲線的通用公式是

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

這個公式也可以按照二階的通用公式的推導方法而來。

四階與五階貝塞爾曲線展示

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線
貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

通用公式

如果從一階開始羅列出幾個公式,就可以總結一個通用的公式。

給定點P0、P1、…、Pn,其貝塞爾曲線即:

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

對公式  

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

前兩個部分進行一下說明,後面的部分都比較容易了解

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

  表示對i 從0開始到n 有 n個式子,對所有式子的結果進行求和,式子計算的規則就是在它後面的表達式

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

這個參數是一個系數,它的計算方法是

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

即 n的階乘除以,i的階乘與n-i的階乘之和,例如對于 n = 5,i = 3 計算的的結果是,

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

如果利用這個公式計算四階公式,可以得出:

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

如何在安卓中使用貝塞爾曲線

經過上面的動畫展示可以看到貝塞爾是一個可控制的平滑的曲線,那麼怎麼在安卓中使用呢。

上面的公式每個點隻有一個參數參與計算,實際上點是由兩個參數X,Y組成,那在使用公式時,分别對所有點計算X的貝塞爾曲線,然後在對所有的點計算Y的貝塞爾曲線,最後(X,Y)這個點就是貝塞爾點了。

在Android的繪制線可以使用Path類,在Path類中對二階和三階貝塞爾曲線做了封裝,省去了手寫公式的時間。這兩種貝塞爾曲線比較常用,能滿足大多數開發上的需求,如下

//二階貝賽爾曲線繪制方法
    public void quadTo(float x1, float y1, float x2, float y2)
    public void rQuadTo(float dx1, float dy1, float dx2, float dy2)
    //三階貝賽爾曲線繪制方法
    public void cubicTo(float x1, float y1, float x2, float y2,float x3, float y3)
    public void rCubicTo(float x1, float y1, float x2, float y2,float x3, float y3)
           

quadTo是二階貝塞爾曲線,二階貝塞爾曲線應該有三個點,但是參數中卻給了兩個點,這兩個點中,第一個是控制點,最後一個是結束點,而開始點就是,Path.moveTo到的那個點或者沒有moveTo,那就是原始坐标點。

rQuadTo方法與quadTo一樣,繪制了二階貝塞爾曲線,不同點是,rQuadTo的起始點使用了上一次曲線的終點。而quadTo的起始點隻是Path.moveTo的點

例如下面代碼

Path path = new Path();
path.moveTo(100,100);
path.quadTo(200,200,300,100);
path.rQuadTo(100,100,200,0);//第一次rQuadTo
path.rQuadTo(100,100,200,0);//第二次rQuadTo
           

實際的情況如下圖所示

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

最開始調用的是quadTo方法,繪制完成後Path的終點是(300,100),緊接着調用第一次rQuadTo,那麼它會以上一次繪制的終點,也就是在點(300,100)的基礎之上加上現在的所有的點的坐标,x都加上300,y都加上100, 即path.rQuadTo(100,100,200,0) 等同于,Path先moveTo(300,100),然後在quadTo(100+300,100+100,200+300,0+100),即quadTo(400,200,500,100)

然後第二次調用rQuadTo(100,100,200,0)這個時候上一次繪制的終點變成了第一次rQuadTo的終點,也就是(500,100),要在此基礎之上加上現在的所有的點的坐标,x都加上500,y都加上100,即rQuadTo(100,100,200,0)等同于,Path先moveTo(500,100),然後再quadTo(100+500.100+100,200+500,0+100),即quadTo(600,200,700,100);

最後繪制的線如下圖的曲線部分所示

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

 rCubicTo的含義與rQuadTo類似,都是參照之前繪制的終點加上現在的坐标然後進行繪制

水波紋效果能量球的實作

1. 先畫出水波紋

按照下圖,矩形代表手機螢幕,畫一個波浪線,它由多個貝塞爾曲線首尾相接組成,整個波浪線從A點開始繪制

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

圖中A,B,C,D四個點組成了兩個貝塞爾曲線,每個貝塞爾曲線橫坐标方向的長度都是200,一個是 ABC三個點組成的,另一個一個是CDE三個點組成的,這兩個貝塞爾曲線的形狀是一樣的,隻不過後者是前者的倒影,兩個貝塞爾曲線組成一組,每一組的形狀都是一樣的,一組水準長度總共是400,然後再水準方向向右再繪制幾組超過右側螢幕即可,這樣先把波浪線繪制完成,然後讓它水準循環向右運動,就可以實作動态水波紋的效果。

下圖表示整個波浪線向右運動了200個機關

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

如果整個波浪線向右運動了兩個貝塞爾曲線的長度,也就是一組的長度後,整個波浪線的起始點A即将進入螢幕,如下圖所示,如果再向右運動那麼起始點A就進入了螢幕,曲線左邊就會出現空白,這個時候讓A點回到最初的位置重新繪制曲線,然後繼續下一次的動畫,這樣就能實作循環的水波紋繪制了。

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

其實這個波浪線也可以用多階的貝塞爾曲線來完成,如果用三階的貝塞爾曲線,以圖中的例子,就是用A、B、D、E,這四個點來完成,A作為開始點,E作為結束點,然後B、D作為控制點。繪制幾個這樣的三階貝塞爾曲線首尾相接即可。除了三階的之外還可以用更高階的貝塞爾曲線完成,這隻需要多設定幾個控制點,做好前後銜接就行。

下面看下代碼的實作

由于水波紋是首尾相接的多個貝塞爾曲線構成,那麼可以設定好Path的起點,然後調用rQuadTo方法傳入每個控制點的坐标與之前的坐标的相對位置即可,這樣起點變化後,後續的控制點也會跟着變化。

實作這個效果,需要自定義View,建立一個類繼承View類,重寫onDraw方法即可

先做設定成員變量

int startX = -400;
    int startY = 400;
    Path bezierPath = new Path();
    Paint paint = new Paint();

           

然後初始化

paint.setColor(Color.BLACK);
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(10);
           

onDraw方法

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        bezierPath.reset();
        //先讓Path移動到起始點,A
        bezierPath.moveTo(startX,startY);
        // 繪制貝塞爾曲線ABC
        // 然後參照A點,設定偏移的大小,B點相對A點偏移(100,-100),C點相對A點偏移(200,0)
        bezierPath.rQuadTo(100,-100,200,0);
        // 繪制貝塞爾曲線CDE
        // 這次的起點是上一次繪制的終點,也就是C點
        // D點相對C點偏移(100,100) E點相對C點偏移(200,0)
        bezierPath.rQuadTo(100,100,200,0);

        // 繪制下一組貝塞爾曲線,過程和第一組一緻
        bezierPath.rQuadTo(100,-100,200,0);
        bezierPath.rQuadTo(100,100,200,0);


        bezierPath.rQuadTo(100,-100,200,0);
        bezierPath.rQuadTo(100,100,200,0);

        bezierPath.rQuadTo(100,-100,200,0);
        bezierPath.rQuadTo(100,100,200,0);

        //開始繪制水波紋Path
        canvas.drawPath(bezierPath,paint);

        //設定x水準向右移動,垂直方向不動
        startX+=20;

        //如果起始點到達螢幕左側,就從初始位置開始繪制
        if (startX>=0){
            startX = -400;
        }

        //重繪
        invalidate();
    }
           

每次繪制完成之後,起始點X的坐标就向右移動,然後下一次繪制的波浪線就會跟着向右,達到水波紋動畫的效果

看下效果

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

好吧,看起來稍微有點奇怪,這可能是曲線的高度有點高,然後長度也不夠長導緻的,調整一下參數試試,起點X修改為-800

int startX = -800;
    int startY = 400;
           

onDraw()方法

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        bezierPath.reset();
        bezierPath.moveTo(startX,startY);
        bezierPath.rQuadTo(200,-50,400,0);
        bezierPath.rQuadTo(200,+50,400,0);
        bezierPath.rQuadTo(200,-50,400,0);
        bezierPath.rQuadTo(200,+50,400,0);
        bezierPath.rQuadTo(200,-50,400,0);
        bezierPath.rQuadTo(200,+50,400,0);
        canvas.drawPath(bezierPath,paint);
        startX+=20;
        if (startX>=0){
            startX = -800;
        }
        invalidate();
    }
           

每個貝塞爾曲線的長度加長一點,變成了400,這樣每一組的長度就有800,是以起點的X坐标設定成了-800,貝塞爾曲線的高度也從100降低到了50,

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

變化的有些緩慢,調整一下X坐标每次改變的大小即可

這次感覺有點像了。

2. 實作水波紋上升

現在隻是有了水波紋的效果,但是水波紋能量球是從底向上一點點增大的,那麼讓Y坐标也跟着變試試。

首先在onLayout中擷取控件的高度

@Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        //從底向上升
        startY = getMeasuredHeight();
    }
           

然後在onDraw方法中設定高度每次繪制都減少1

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        bezierPath.reset();
        bezierPath.moveTo(startX,startY);
        bezierPath.rQuadTo(200,-50,400,0);
        bezierPath.rQuadTo(200,+50,400,0);
        bezierPath.rQuadTo(200,-50,400,0);
        bezierPath.rQuadTo(200,+50,400,0);
        bezierPath.rQuadTo(200,-50,400,0);
        bezierPath.rQuadTo(200,+50,400,0);
        canvas.drawPath(bezierPath,paint);
        startX+=20;
        if (startX>=0){
            startX = -800;
        }
        if (startY>0){
            //從底部開始向上升
            startY --;
            invalidate();
        }


    }
           

看下效果

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

水波紋上升的有些緩慢。需要增大Y減少的幅度

3. 繪制能量球

最後一步是繪制球形,其實就是繪制一個圓形,然後把水波紋繪制成實心再加上顔色即可。

這個需要用到Canvas的clipPath方法,從View中割出一個圓形來,調用這個方法之後,該控件隻顯示被剪裁的部分,canvas其他的不可見,這樣就實作了能量球的繪制。

先添加圓形路徑,然後在onLayout方法中設定path為圓形

float halfX = (int) (getMeasuredWidth() / 2f);
int halfY = (int) (getMeasuredHeight() / 2f);
//設定一個圓形路徑
circlePath.addCircle(halfX, halfY, Math.min(halfX, halfY), Path.Direction.CW);
       
           

然後在onDraw方法最開始的位置添加切割圓形的代碼,并繪制圓形

//切割一個圓形
canvas.clipPath(circlePath);
//繪制圓形
canvas.drawPath(circlePath, circlePaint);
           

最後的效果如下

貝塞爾曲線及應用貝塞爾曲線介紹貝塞爾曲線公式推導如何在安卓中使用貝塞爾曲線

OK,整個水波紋能量球就繪制完成了,下面是全部代碼

package com.wx.beziercurvestudy;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;


/**
 * 繪制水波紋能量球
 */
public class BezierWaterRippleView extends View {

    /**
     * X起始點
     */
    public static final int START_X = -800;
    /**
     * X每次減少的步長
     */
    public static final int X_STEP = 20;
    /**
     * Y每次減少的步長
     */
    public static final int Y_STEP = 5;
    public static final int BEZIER_LENGTH = 200;
    public static final int BEZIER_HEIGHT = -50;
    Path circlePath = new Path();
    Paint circlePaint = new Paint();

    int startX = START_X;
    int startY = 0;
    Path bezierPath = new Path();
    Paint bezierPaint = new Paint();

    public BezierWaterRippleView(Context context) {
        this(context, null);
    }

    public BezierWaterRippleView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BezierWaterRippleView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        circlePaint.setColor(Color.BLACK);
        circlePaint.setStrokeWidth(5);
        circlePaint.setStyle(Paint.Style.STROKE);

        bezierPaint.setColor(Color.BLUE);
        bezierPaint.setStyle(Paint.Style.FILL);
        bezierPaint.setStrokeWidth(10);

    }


    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        float halfX = (int) (getMeasuredWidth() / 2f);
        int halfY = (int) (getMeasuredHeight() / 2f);
        //設定一個圓形路徑
        circlePath.addCircle(halfX, halfY, Math.min(halfX, halfY), Path.Direction.CW);
        //從底向上升
        startY = getMeasuredHeight();
    }

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

        //切割一個圓形
        canvas.clipPath(circlePath);
        //繪制圓形
        canvas.drawPath(circlePath, circlePaint);

        bezierPath.reset();
        //設定起點
        bezierPath.moveTo(startX, startY);
        //設定貝塞爾曲線路徑
        bezierPath.rQuadTo(BEZIER_LENGTH, -BEZIER_HEIGHT, BEZIER_LENGTH * 2, 0);
        bezierPath.rQuadTo(BEZIER_LENGTH, BEZIER_HEIGHT, BEZIER_LENGTH * 2, 0);

        bezierPath.rQuadTo(BEZIER_LENGTH, -BEZIER_HEIGHT, BEZIER_LENGTH * 2, 0);
        bezierPath.rQuadTo(BEZIER_LENGTH, BEZIER_HEIGHT, BEZIER_LENGTH * 2, 0);

        bezierPath.rQuadTo(BEZIER_LENGTH, -BEZIER_HEIGHT, BEZIER_LENGTH * 2, 0);
        bezierPath.rQuadTo(BEZIER_LENGTH, BEZIER_HEIGHT, BEZIER_LENGTH * 2, 0);

        //下面三行代碼設定封閉的形狀,繪制水波紋下面的陰影部分。
        //右下角
        bezierPath.lineTo(getMeasuredWidth(), getMeasuredHeight());
        //左下角
        bezierPath.lineTo(0, getMeasuredHeight());
        //起點
        bezierPath.lineTo(startX, startY);

        bezierPath.close();
        //繪制貝塞爾曲線
        canvas.drawPath(bezierPath, bezierPaint);


        //垂直方向開始移動
        if (startY > 0) {

            //水準向右移動
            startX += X_STEP;
            //到達螢幕最左側時,重新回到水準方向的起點
            if (startX >= 0) {
                startX = START_X;
            }

            startY -= Y_STEP;
            invalidate();

        }

    }

    /**
     * 重新繪制
     */
    public void reDraw() {
        startX = START_X;
        startY = getMeasuredHeight();
        invalidate();
    }
}
           

安卓中隻封裝了常見的二階和三階的繪制,對于多階的曲線,可以手動操作Path類,将t從0到1變化過程中的點的集合通過公式求得,然後依次添加到Path中,再繪制即可,例如四階的實作方式如下:

public void setFourthBezierCurvePath(Point P0, Point P1, Point P2, Point P3, Point P4, Path path) {
        int num = 0;
        for (int i = 0; i < 100; i++) {
            
            int t = (int) (num / 100f);
            
            float subT = 1 - t;

            //帶入四階公式進行計算
            int bezierX = (int) (P0.x * subT * subT * subT * subT
                    + 4 * P1.x * subT * subT * subT * t
                    + 6 * P2.x * subT * subT * t * t
                    + 4 * P3.x * subT * t * t * t
                    + P4.x * t * t * t * t);
            
            int bezierY = (int) (P0.y * subT * subT * subT * subT
                    + 4 * P1.y * subT * subT * subT * t
                    + 6 * P2.y * subT * subT * t * t
                    + 4 * P3.y * subT * t * t * t
                    + P4.y * t * t * t * t);
            //記錄目前t值下的貝塞爾曲線點
            path.lineTo(bezierX,bezierY);
            
            num++;
        }

    }
           

給Path設定好之後,就可以使用Canvas進行繪制,即可得到對應的貝塞爾曲線。

貝塞爾曲線可以實作很多特效,隻要涉及到路徑動态變化,都可以考慮使用它,例如簡單的翻頁效果,QQ上面的移除未讀消息角标的軌迹等等。隻要我們預先設計好曲線的軌迹,就可以實作炫酷的動效。

參考資料

百度百科-貝塞爾曲線

n階bezier曲線 通用公式說明和應用 - 雜七雜八

n 階貝塞爾曲線計算公式實作 - Duan的部落格

Android自定義View——貝塞爾曲線實作水波紋效果

canvas進階之貝塞爾公式推導與物體跟随複雜曲線的軌迹運動

Android自定義View(四) Path之貝塞爾曲線