自定義view-貝塞爾曲線的簡單使用

理解貝塞爾曲線的原理
貝塞爾曲線是用一系列點來控制曲線狀態的,我將這些點簡單分爲兩類:數據點、控制點。通過調整控制點,貝塞爾曲線形狀會發生變化。

數據點:確定曲線的起始和結束位置
控制點:確定曲線的彎曲程度

一階曲線原理
一階曲線是沒有控制點的,僅有兩個數據點(A 和 B),最終效果一個線段。
在這裏插入圖片描述
一階公式如下:
一階公式如下:
二階曲線原理
二階曲線由兩個數據點(A 和 C),一個控制點(B)來描述曲線狀態,大致如下:
在這裏插入圖片描述
那麼AC之間的紅線是怎麼生成的呢,讓我們瞭解一下
在這裏插入圖片描述
在AB線段和BC線段分別去D、E兩點,且滿足條件
在這裏插入圖片描述
連接DE,取點F,使得: ,這樣獲取到的點F就是貝塞爾曲線上的一個點,動態圖如下:
在這裏插入圖片描述
二階公式如下:
在這裏插入圖片描述
三階曲線原理
三階曲線由兩個數據點(A 和 D),兩個控制點(B 和 C)來描述曲線狀態
在這裏插入圖片描述
動態圖如下:
在這裏插入圖片描述
三階公式如下:
在這裏插入圖片描述
四階曲線
在這裏插入圖片描述
五階曲線
在這裏插入圖片描述
通用公式:
在這裏插入圖片描述

實現簡單的小例子
在我們Android中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()方法
讓我們先來看一下源碼

	/**
     * Add a quadratic bezier from the last point, approaching control point
     * (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for
     * this contour, the first point is automatically set to (0,0).
     *
     * @param x1 The x-coordinate of the control point on a quadratic curve
     * @param y1 The y-coordinate of the control point on a quadratic curve
     * @param x2 The x-coordinate of the end point on a quadratic curve
     * @param y2 The y-coordinate of the end point on a quadratic curve
     */
    public void quadTo(float x1, float y1, float x2, float y2) {
        isSimplePath = false;
        native_quadTo(mNativePath, x1, y1, x2, y2);
    }

從源碼的註釋上我們可以得到的信息如下:參數中(x1,y1)是控制點座標,(x2,y2)是終點座標 。

大家可能會有一個疑問:有控制點和終點座標,那起始點是多少呢? 整條線的起始點是通過Path.moveTo(x,y)來指定的,而如果我們連續調用quadTo(),前一個quadTo()的終點,就是下一個quadTo()函數的起點;如果初始沒有調用Path.moveTo(x,y)來指定起始點,則默認以控件左上角(0,0)爲起始點;

rQuadTo()
先來看一下它的源碼,代碼如下:

	/**
     * Same as quadTo, but the coordinates are considered relative to the last
     * point on this contour. If there is no previous point, then a moveTo(0,0)
     * is inserted automatically.
     *
     * @param dx1 The amount to add to the x-coordinate of the last point on
     *            this contour, for the control point of a quadratic curve
     * @param dy1 The amount to add to the y-coordinate of the last point on
     *            this contour, for the control point of a quadratic curve
     * @param dx2 The amount to add to the x-coordinate of the last point on
     *            this contour, for the end point of a quadratic curve
     * @param dy2 The amount to add to the y-coordinate of the last point on
     *            this contour, for the end point of a quadratic curve
     */
    public void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
        isSimplePath = false;
        native_rQuadTo(mNativePath, dx1, dy1, dx2, dy2);
    }

從上面的方法註釋我們可以看到,這是一個相對座標,具體參數意思如下:

dx1:控制點X座標,表示相對上一個終點X座標的位移座標,可爲負值,正值表示相加,負值表示相減;
dy1:控制點Y座標,相對上一個終點Y座標的位移座標。同樣可爲負值,正值表示相加,負值表示相減;
dx2:終點X座標,同樣是一個相對座標,相對上一個終點X座標的位移值,可爲負值,正值表示相加,負值表示相減;
dy2:終點Y座標,同樣是一個相對,相對上一個終點Y座標的位移值。可爲負值,正值表示相加,負值表示相減;

cubicTo()
這是Android的三階貝塞爾曲線方法,先來看一下每一參數的意義

	/**
     * Add a cubic bezier from the last point, approaching control points
     * (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been
     * made for this contour, the first point is automatically set to (0,0).
     *
     * @param x1 The x-coordinate of the 1st control point on a cubic curve
     * @param y1 The y-coordinate of the 1st control point on a cubic curve
     * @param x2 The x-coordinate of the 2nd control point on a cubic curve
     * @param y2 The y-coordinate of the 2nd control point on a cubic curve
     * @param x3 The x-coordinate of the end point on a cubic curve
     * @param y3 The y-coordinate of the end point on a cubic curve
     */
    public void cubicTo(float x1, float y1, float x2, float y2,
                        float x3, float y3) {
        isSimplePath = false;
        native_cubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
    }

從上面源碼可以看到參數(x1,y1)是第一個控制點座標,(x2,y2)是第二個控制點座標,(x3,y3)是終點座標。

整條線的起始點是通過Path.moveTo(x,y)來指定的,而如果我們連續調用cubicTo(),前一個cubicTo()的終點,就是下一個cubicTo()函數的起點;如果初始沒有調用Path.moveTo(x,y)來指定起始點,則默認以控件左上角(0,0)爲起始點;和我們的quadTo()方法一樣。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章