貝塞爾曲線

爲何要講貝塞爾曲線,實際上 Android 中不少效果都有用到貝塞爾曲線。html

QQ 的消息拽拖小紅點旗袍消失的效果java

QQ空間 直播頁面右下角的禮物冒泡特效 android

水流波動效果git

圖片或書本翻頁效果github

一個彈性效果的抽屜菜單算法


能夠先對貝塞爾曲線有一個大概的認識。canvas

貝塞爾曲線維基百科api

歷史


貝塞爾曲線的數學基礎是早在 1912 年就廣爲人知的 伯恩斯坦多項式 。但直到 1959 年,當時就任於雪鐵龍的法國數學家 Paul de Casteljau 纔開始對它進行圖形化應用的嘗試,並提出了一種數值穩定的 de Casteljau 算法。然而貝塞爾曲線的得名,倒是因爲 1962 年另外一位就任於雷諾的法國工程師 Pierre Bézier 的普遍宣傳。他使用這種只須要不多的控制點就可以生成複雜平滑曲線的方法,來輔助汽車車體的工業設計。函數

正是由於控制簡便卻具備極強的描述能力,貝塞爾曲線在工業設計領域迅速獲得了普遍的應用。不只如此,在計算機圖形學領域,尤爲是矢量圖形學,貝塞爾曲線也佔有重要的地位。今天咱們最多見的一些矢量繪圖軟件,如 Flash、Illustrator、CorelDraw 等,無一例外都提供了繪製貝塞爾曲線的功能。甚至像 Photoshop 這樣的位圖編輯軟件,也把貝塞爾曲線做爲僅有的矢量繪製工具(鋼筆工具)包含其中。工具

貝塞爾曲線在 Web 開發領域一樣佔有一席之地。CSS3 新增了 transition-timing-function 屬性,它的取值就能夠設置爲一個三次貝塞爾曲線方程。在此以前,也有很多 JavaScript 動畫庫使用貝塞爾曲線來實現美觀逼真的緩動效果。


公式

線性貝塞爾曲線

給定點P0、P1,線性貝塞爾曲線只是一條兩點之間的直線。這條線由下式給出:

二次方貝塞爾曲線

二次方貝塞爾曲線的路徑由給定點P0、P一、P2的函數B(t)追蹤:

三次方貝塞爾曲線

P0、P一、P二、P3 四個點在平面或在三維空間中定義了三次方貝塞爾曲線。曲線起始於 P0 走向 P1 ,並從 P2 的方向來到 P3 。通常不會通過 P1 或 P2 ;這兩個點只是在那裏提供方向資訊。 P0 和 P1 之間的間距,決定了曲線在轉而趨進 P2 以前,走向 P1 方向的「長度有多長」。

曲線的參數形式爲:

n階貝塞爾曲線

n階貝塞爾曲線可以下判斷,給定點P0、p一、...、Pn,其貝塞爾曲線即


看公式仍是有些抽象,接下來能夠看一下圖解,具像的瞭解一下什麼是貝塞爾曲線:以二階貝塞爾曲線和三階貝塞爾曲線爲例。

有一篇文章寫的極好

貝塞爾曲線掃盲

貝塞爾曲線不只能畫直線,也能畫曲線。即使是更復雜的曲線,控制點的增長也只是線性的。這一特色使其不光在工業設計領域大展拳腳,就連數學基礎很差的人也能夠比較容易地掌握,好比大多數平面美術設計師們。

簡單來講,貝塞爾曲線就是將任意一條曲線轉化爲準確的數學公式。 Bezier 曲線是用一系列點來控制曲線狀態的。


一些關鍵的名詞

  • 數據點:一般是指一條路徑的起始點和終止點
  • 控制點:控制點決定了一條路徑的彎曲軌跡,根據控制點的個數,貝塞爾曲線被分爲一階貝塞爾曲線(0個控制點)、二階貝塞爾曲線(1個控制點)、三階貝塞爾曲線(2個控制點),以此類推。

在Android中的應用

Android 開發中,咱們只考慮二階貝塞爾曲線和三階貝塞爾曲線, SDK 也是隻提供了二階和三階的 API 調用。

固然,對於再高階的貝塞爾曲線,一般能夠拆分紅多個低階的貝塞爾曲線。

推薦一個好的貝塞爾曲線的動態演示,能夠很直觀的感覺一下:

myst729.github.io/bezier-curv…

這裏推薦 醫生 的一片博文,已經很是全面的介紹了貝塞爾曲線在 Android 中的一些用法及實例,寫的很好。

貝塞爾曲線開發的藝術

下面的內容都基於這篇文章。

二階貝塞爾曲線在 Android 中的 API 爲:

quadTo 是基於絕對座標,而 rQuadTo 是基於相對座標。

mPath.moveTo(mStartPointX, mStartPointY);
//二階貝塞爾曲線
mPath.quadTo(mAuxiliaryX, mAuxiliaryY, mEndPointX, mEndPointY);
canvas.drawPath(mPath, mPaintBezier);複製代碼

三階貝塞爾曲線在 Android 中的 API 爲:

這兩個API在原理上也是能夠互相轉換的。

兩個點的話涉及到多點觸摸,有興趣能夠看看下面這篇文章。

Android MotionEvent詳解

cubicTo是基於絕對座標,而rCubicTo是基於相對座標。

mPath.moveTo(mStartPointX, mStartPointY);
// 三階貝塞爾曲線
mPath.cubicTo(mAuxiliaryOneX, mAuxiliaryOneY, mAuxiliaryTwoX, mAuxiliaryTwoY, mEndPointX, mEndPointY);
canvas.drawPath(mPath, mPaintBezier);複製代碼

三階貝塞爾曲線其實也沒什麼,就是多了一個控制點,記錄下他的位置就能夠了。

圓滑繪圖

當在屏幕上繪製路徑的時候,咱們一般會經過 Path.lineTo 將各個觸點鏈接起來,可是這樣確定會很生硬。由於是經過直線來鏈接的。若是經過二階貝塞爾曲線,就會圓滑不少。不會出現太多的生硬鏈接。

if (dx >= offset || dy >= offset) {
                    // 貝塞爾曲線的控制點爲起點和終點的中點
                    float cX = (x1 + preX) / 2;
                    float cY = (y1 + preY) / 2;
                    mPath.quadTo(preX, preY, cX, cY);
// mPath.lineTo(x1, y1);
                    mX = x1;
                    mY = y1;
                }複製代碼

經過紀錄 Move 過程當中點位置的變化,而後傳入 quadTo 中的參數,就能夠實現圓滑的繪圖。

根據公式咱們能夠模仿着寫一個工具類:

public class BezierUtil {

    /** * 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;
    }

    /** * B(t) = P0 * (1-t)^3 + 3 * P1 * t * (1-t)^2 + 3 * P2 * t^2 * (1-t) + P3 * t^3, t ∈ [0,1] * * @param t 曲線長度比例 * @param p0 起始點 * @param p1 控制點1 * @param p2 控制點2 * @param p3 終止點 * @return t對應的點 */
    public static PointF CalculateBezierPointForCubic(float t, PointF p0, PointF p1, PointF p2, PointF p3) {
        PointF pointF = new PointF();
        float temp = 1- t;
        pointF.x = p0.x * temp * temp * temp + 3 * p1.x * t * temp * temp + 3 * p2.x * t * t * temp + p3.x * t * t * t;
        pointF.y = p0.y * temp * temp * temp + 3 * p1.y * t * temp * temp + 3 * p2.y * t * t * temp + p3.y * t * t * t;
        return pointF;
    }


}複製代碼

推薦一個關於貝塞爾曲線的開源項目:

github.com/venshine/Be… ( 經過 de Casteljau 算法繪製貝塞爾曲線,並計算它的切線,實現 1-7 階貝塞爾曲線的造成動畫 )

參考博客:

Android 繪製 N 階 Bezier 曲線

相關文章
相關標籤/搜索