我想學前端動畫-前端的貝塞爾

我想學前端動畫

最近想學習前端動畫,準備先從css3的動畫開始。
css3的動畫主要是

  • transition
  • animation

transition有animation-timing-function
animation有animation-timing-function
均內置 ease,linear,ease-in,ease-out,ease-in-out。
還可以自定義cubic-bizier(n,n,n,n), 這個嘛玩意呢,三階貝塞爾曲線。


說道這裏, 回想一下我們前端在哪些地方還會貝塞爾呢。

  • svg
  • canvas/webgl
  • css3 動畫

說過了,本人想學前端動畫,於是這個坎過不去。


什麼是貝爾賽曲線。

貝塞爾曲線(Bézier curve),又稱貝茲曲線或貝濟埃曲線,是應用於二維圖形應用程序的數學曲線。
再多的就自己查google, 什麼google用不了? 程序員不會翻牆? oh, no!

通用公式

線性公式

二次方公式

三次方公式

再多的,額, 暫時學不動了。

一階二階三階封裝

接下來我們,我們如果要取點怎麼辦呢? 不要着急。
代碼不多, 這就是基於上面公式的簡單封裝,
你傳入需要的點數量和相應的控制點就能獲得相應一組點的信息。

class Bezier {
  getPoints(count = 100, ...points) {
    const len = points.length;
    if (len < 2 || len > 4) {
      throw new Error("參數points的長度應該大於等於2小於5");
    }
    const fn =
      len === 2
        ? this.firstOrder
        : len === 3
        ? this.secondOrder
        : this.thirdOrder;
    const retPoints = [];
    for (let i = 0; i < count; i++) {
      retPoints.push(fn.call(null, i / count, ...points));
    }
    return retPoints;
  }

  firstOrder(t, p0, p1) {
    const { x: x0, y: y0 } = p0;
    const { x: x1, y: y1 } = p1;
    const x = (x1 - x0) * t;
    const y = (y1 - y0) * t;
    return { x, y };
  }

  secondOrder(t, p0, p1, p2) {
    const { x: x0, y: y0 } = p0;
    const { x: x1, y: y1 } = p1;
    const { x: x2, x: y2 } = p2;
    const x = (1 - t) * (1 - t) * x0 + 2 * t * (1 - t) * x1 + t * t * x2;
    const y = (1 - t) * (1 - t) * y0 + 2 * t * (1 - t) * y1 + t * t * y2;
    return { x, y };
  }

  thirdOrder(t, p0, p1, p2, p3) {
    const { x: x0, y: y0 } = p0;
    const { x: x1, y: y1 } = p1;
    const { x: x2, y: y2 } = p2;
    const { x: x3, y: y3 } = p3;
    let x =
      x0 * Math.pow(1 - t, 3) +
      3 * x1 * t * (1 - t) * (1 - t) +
      3 * x2 * t * t * (1 - t) +
      x3 * t * t * t;
    let y =
      y0 * (1 - t) * (1 - t) * (1 - t) +
      3 * y1 * t * (1 - t) * (1 - t) +
      3 * y2 * t * t * (1 - t) +
      y3 * t * t * t;
    return { x, y };
  }
}

export default new Bezier();

可能,你覺得太空洞,那麼我們看一下demo和截圖。
演示地址https://xiangwenhu.github.io/Bezier/

到此完了麼? 沒有!

定義三階貝塞爾關鍵點

回到最開始, animation和 transition都可以自定義三階貝塞爾函數, 而需要的就是兩個控制點的信息。
在線取三階貝塞爾關鍵的方案早就有了。

在線貝塞爾
在線貝塞爾2

但是不妨礙我自己去實現一個簡單,方便我加強理解。
大致的實現思路

  • canvas 繪製效果
  • 兩個控制點用dom元素來顯示

邏輯

  • 點擊時計算最近的點,同時修改最近點的座標
  • 重繪

當然這只是一個簡單的版本。

演示地址: https://xiangwenhu.github.io/Bezier/d.html
截圖:

參考:

貝塞爾曲線掃盲
在線貝塞爾
在線貝塞爾2
可視化n次貝塞爾曲線及過程動畫演示--大寶劍
貝塞爾曲線算法,js貝塞爾曲線路徑點
貝塞爾曲線算法之JS獲取點
https://github.com/mtsee/Bezier/blob/master/src/bezier.js
n 階貝塞爾曲線計算公式實現
前端貝塞爾曲線效果彙總

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