貝塞爾曲線算法之JS獲取點

原文鏈接:https://segmentfault.com/a/1190000018597975?tdsourcetag=s_pcqq_aiomsg

貝塞爾曲線算法之JS獲取點

饅頭老哥的一篇文章,對貝塞爾曲線分析的很徹底,這裏轉載一下。
順便推廣一下他個人開發的可擴展的HTML5可視化編輯器www.h5ds.com

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

在這裏插入圖片描述

這個一階貝塞爾曲線繪製過程,黑點按百分比t從P0->P1移動,看不出什麼呢~ 那繼續看後面的圖

在這裏插入圖片描述

這個是二階貝塞爾曲線,從P0->P1有個小綠點按百分比t運動,從P1->P2也有個小綠點按百分比t運動,兩個綠點之間也有個小黑點按百分比t運動,這個黑點產生的軌跡就是一個二階貝塞爾曲線。
在這裏插入圖片描述

這個是三階貝塞爾曲線,同理,綠點有3個,點與點之間都是按百分比t運動,最終得到一個小黑點。這個小黑點的運動軌跡就是三階貝塞爾。
在這裏插入圖片描述

同理,還有四階貝塞爾。

在這裏插入圖片描述

同理,六階貝塞爾,N階貝塞爾。

實際上,我們的運用中,3階貝塞爾就已經足夠滿足我們的業務需求了,生活中,多個三階貝塞爾曲線可以組合成任意一條曲線,我們的photoshop裏面的鋼筆工具就是3階貝塞爾曲線實現的。
貝塞爾曲線方程解析
數學家已經給了我們公式:
在這裏插入圖片描述

不好意思,高數還給了老師,這尼瑪公式看不懂啊~ 沒關係,我們簡化下就能看懂了。

// t是百分比,a是參數

// 1階貝塞爾曲線公式
function onebsr(t, a1, a2) {
    return a1 + (a2 - a1) * t;
}

// 2階貝塞爾曲線公式
function twobsr(t, a1, a2, a3) {
    return ((1 - t) * (1 - t)) * a1 + 2 * t * (1 - t) * a2 + t * t * a3;
}

// 3階貝塞爾曲線公式
function threebsr(t, a1, a2, a3, a4) {
    return a1 * (1 - t) * (1 - t) * (1 - t) + 3 * a2 * t * (1 - t) * (1 - t) + 3 * a3 * t * t * (1 - t) + a4 * t * t * t;
}

根據公式,我們可以帶入座標進行計算

/**
     * @desc 一階貝塞爾
     * @param {number} t 當前百分比
     * @param {Array} p1 起點座標
     * @param {Array} p2 終點座標
     */
    oneBezier(t, p1, p2) {
        const [x1, y1] = p1;
        const [x2, y2] = p2;
        let x = x1 + (x2 - x1) * t;
        let y = y1 + (y2 - y1) * t;
        return [x, y];
    }

    /**
     * @desc 二階貝塞爾
     * @param {number} t 當前百分比
     * @param {Array} p1 起點座標
     * @param {Array} p2 終點座標
     * @param {Array} cp 控制點
     */
    twoBezier(t, p1, cp, p2) {
        const [x1, y1] = p1;
        const [cx, cy] = cp;
        const [x2, y2] = p2;
        let x = (1 - t) * (1 - t) * x1 + 2 * t * (1 - t) * cx + t * t * x2;
        let y = (1 - t) * (1 - t) * y1 + 2 * t * (1 - t) * cy + t * t * y2;
        return [x, y];
    }

    /**
     * @desc 三階貝塞爾
     * @param {number} t 當前百分比
     * @param {Array} p1 起點座標
     * @param {Array} p2 終點座標
     * @param {Array} cp1 控制點1
     * @param {Array} cp2 控制點2
     */
    threeBezier(t, p1, cp1, cp2, p2) {
        const [x1, y1] = p1;
        const [x2, y2] = p2;
        const [cx1, cy1] = cp1;
        const [cx2, cy2] = cp2;
        let x =
            x1 * (1 - t) * (1 - t) * (1 - t) +
            3 * cx1 * t * (1 - t) * (1 - t) +
            3 * cx2 * t * t * (1 - t) +
            x2 * t * t * t;
        let y =
            y1 * (1 - t) * (1 - t) * (1 - t) +
            3 * cy1 * t * (1 - t) * (1 - t) +
            3 * cy2 * t * t * (1 - t) +
            y2 * t * t * t;
        return [x, y];
    }

算法封裝
我把貝塞爾曲線封裝了下,添加了一個獲取路徑點的方法,然後使用span標籤繪製到頁面上的效果。

我們看看DEMO中1~3階貝塞爾曲線上獲取點的效果
在這裏插入圖片描述
在這裏插入圖片描述在這裏插入圖片描述
demo的github地址:https://github.com/mtsee/Bezier

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