<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] # 什么是貝塞爾曲線 貝塞爾曲線于 1962 年,由法國工程師皮埃爾·貝濟埃(Pierre Bézier)所廣泛發表,他運用貝塞爾曲線來為汽車的主體進行設計。 <br> 貝塞爾曲線主要用于二維圖形應用程序中的數學曲線,曲線由起始點,終止點(也稱錨點)和控制點組成,通過調整控制點,通過一定方式繪制的貝塞爾曲線形狀會發生變化。后面會具體介紹繪制的方法。 <br> 在計算機圖形學中貝賽爾曲線的運用很廣泛,例如Photoshop中的鋼筆效果,Flash5的貝塞爾曲線工具,在軟件GUI開發中一般也會提供對應的方法來實現貝賽爾曲線,我們熟知的CSS動畫過渡時間函數也是通過貝塞爾曲線(三階貝塞爾曲線)獲取的。 <br> <br> # 貝塞爾曲線分為哪些類型? 貝塞爾曲線根據**控制點**的數量分為: * 一階貝塞爾曲線(2 個控制點) * 二階貝塞爾曲線(3 個控制點) * 三階貝塞爾曲線(4 個控制點) * n階貝塞爾曲線(n+1 個控制點) <br> <br> # 貝塞爾曲線是如何繪制出來的 下面以二街貝塞爾曲線為例。 在平面內任選 3 個不共線的點,依次用線段連接 ![](https://box.kancloud.cn/089a8f8bf9d7aa7b53c316fc117a25d8_600x400.png) <br> 在第一條線段上任選一個點 D。計算該點到線段起點的距離 AD,與該線段總長 AB 的比例。 ![](https://box.kancloud.cn/cd107c07168b5fd14837f27c1b3bf55c_600x400.png) <br> 根據上一步得到的比例,從第二條線段上找出對應的點 E,使得`AD:AB = BE:BC`。 ![](https://box.kancloud.cn/0229cf90024260cdc0bd934d9188889c_600x400.png) <br> 連接這兩點 DE。 ![](https://box.kancloud.cn/76cd205a6c5be54d8986ace4d9a79c46_600x400.png) <br> 從新的線段 DE 上再次找出相同比例的點 F,使得`DF:DE = AD:AB = BE:BC`。 ![](https://box.kancloud.cn/e14ef5104012aee14b09da3bf68040a4_600x400.png) <br> 到這里,我們就確定了貝塞爾曲線上的一個點 F。接下來,請稍微回想一下中學所學的極限知識,讓選取的點 D 在第一條線段上從起點 A 移動到終點 B,找出所有的貝塞爾曲線上的點 F。所有的點找出來之后,我們也得到了這條貝塞爾曲線。 ![](https://box.kancloud.cn/9e0cb96e47a0978d16aa5e38403cc35f_600x400.png) <br> 繪制過程如圖 ![](https://box.kancloud.cn/b37019efc7a089bd7681c36f4c518e45_360x150.gif) <br> 當控制點個數為 4 時,步驟都是相同的,只不過我們每確定一個貝塞爾曲線上的點,要進行三輪取點操作。如圖,`AE:AB = BF:BC = CG:CD = EH:EF = FI:FG = HJ:HI`,其中點 J 就是最終得到的貝塞爾曲線上的一個點。 ![](https://box.kancloud.cn/9c924e0683dea75b1d489b916d17a0d3_600x400.png) <br> 這樣我們得到的是一條三次貝塞爾曲線。 ![](https://box.kancloud.cn/a3b3abdd71def18b60bedc1d2a153034_600x400.png) <br> <br> # 如何求貝塞爾曲線上的點坐標? ## 一階貝塞爾曲線 ![](https://box.kancloud.cn/99302ca3c0b218c37bb6c305f9e6c5c8_240x100.gif) 對于一階貝塞爾曲線,我們可以通過幾何知識,很容易根據 t 的值得出線段上那個點的坐標: ![](https://box.kancloud.cn/52954c8e5f037d4acd1de92a8e4d15ee_221x26.png) <br> 然后可以得出: ![](https://box.kancloud.cn/d49162c4700ef6dfd4d71078f357e420_300x26.png) <br> ## 二階貝塞爾曲線 ![](https://box.kancloud.cn/21c0261c945a079446bd129622bac9fb_240x100.gif) 對于二階貝塞爾曲線,其實你可以理解為:在`P0P1`上利用一階公式求出點`P0'`,然后在`P1P2`上利用一階公式求出點`P1'`,最后在`P0'P1'`上再利用一階公式就可以求出最終貝塞爾曲線上的點`P0''`。具體推導過程如下: > 先求出線段上的控制點。 ![](https://box.kancloud.cn/6a91439e03a025429e07035337e7aca6_190x30.png) ![](https://box.kancloud.cn/42096ea837fa42d044c6db97955604ad_190x30.png) <br> > 將上面的公式帶入至下列公式中: ![](https://box.kancloud.cn/946062ad4e67cbc2636f1979ea283da5_217x30.png) ![](https://box.kancloud.cn/d500e35bfbf2bb7601da8ecba7e2551e_425x26.png) ![](https://box.kancloud.cn/785fb5e5835c21a9cc83514ee8845b9a_306x29.png) <br> > 得出以下公式: ![](https://box.kancloud.cn/a3d819414510e2f311554fdc3969e9ca_446x29.png) <br> ## 三階貝塞爾曲線 ![](https://box.kancloud.cn/4ed064f5183fcfa327be33d9336232a1_240x100.gif) 將 `P0P1P2 `與 `P1P2P3` 看成是2個2階段貝塞爾曲線,可根據上面分別求得坐標點公式: ![](https://box.kancloud.cn/795ec4915249f0f48f648d8639b190fa_768x69.png) ![](https://box.kancloud.cn/a16fb6fbea8e744855d654f8dfaf97c4_770x69.png) <br> 將 p0''與p1''連接,根據之前的比例找到點P0''',根據一階貝塞爾曲線,可得到公式: ![](https://box.kancloud.cn/cb24265e582f0f2659882dc4ed4df4e1_594x62.png) <br> 分別將P0''和P1''代入以上公式,可得: ![](https://box.kancloud.cn/258b32aac8e710b662ef24ceb9693e7f_591x29.png) <br> ## 多階貝塞爾曲線 ![](https://box.kancloud.cn/a141d309731f3a70b27315afec616ba0_334x62.png) 即: ![](https://box.kancloud.cn/7cd169ffffd49b53fe2ee9870d75d24e_259x62.png) <br> <br> # 動態繪制貝塞爾曲線 詳細見 [CodePen](https://codepen.io/surahe/pen/VNoOpd) ~~~ /** * 遍歷 points,畫出對應的點并用線連起來 * @param {Array} points */ function drawCubicBezierCurzeHelper(points) { ctx.save() // 遍歷 points 的坐標,畫線 points.reduce((p, c) => { ctx.strokeStyle = "gray" drawLine(...p, ...c) return c }) // 遍歷 points 的坐標,畫紅點 points.forEach((c) => { ctx.beginPath() ctx.fillStyle = 'red'; ctx.arc(...c, 20, 0, 2 * Math.PI); ctx.fill() }) ctx.restore() } /** * 逐個畫出貝塞爾曲線上的點 */ function animation2() { if (t >= 1) { // 初始點動畫執行完畢標志 isEnded = true; return } // 獲取當前 t 的點坐標 let initPoint2 = drawPoints(points) ctx.strokeStyle = "blue" // 以初始點和當前點畫線 drawLine(...initPoint, ...initPoint2) // 將當前點設置為初始點 initPoint = initPoint2 // 應該是使用緩存優化性能 cache = canvas.toDataURL("image/jpeg", 1); let img = new Image(); img.src = cache img.onload = function () { ctx.drawImage(img, 0, 0, canvas.width, canvas.height) // 遞歸執行 window.requestAnimationFrame(() => { t += 0.1 animation2() }) } } ~~~ <br> <br> # SVG 與 貝塞爾曲線 path的標簽,可以繪制任意的路徑,包括貝塞爾曲線。 <br> 三次貝塞爾曲線指令:`C x1 y1, x2 y2, x y`兩個控制點`(x1,y1)`和(`x2,y2)`,`(x,y)`代表曲線的終點。字母`C`表示特定動作與行為,這里需要大寫,表示標準三次方貝塞爾曲線。 <br> 下面一些描述貝塞爾曲線的代碼(片段),其中字母M表示特定動作moveTo, 指將繪圖的起點移動到此處。 ~~~ <svg width="190px" height="160px"> <path d="M10 10 C 20 20, 40 20, 50 10" stroke="3" fill="none"/> <path d="M70 10 C 70 20, 120 20, 120 10" stroke="3" fill="none"/> <path d="M130 10 C 120 20, 180 20, 170 10" stroke="3" fill="none"/> <path d="M10 60 C 20 80, 40 80, 50 60" stroke="3" fill="none"/> <path d="M70 60 C 70 80, 110 80, 110 60" stroke="3" fill="none"/> <path d="M130 60 C 120 80, 180 80, 170 60" stroke="3" fill="none"/> <path d="M10 110 C 20 140, 40 140, 50 110" stroke="3" fill="none"/> <path d="M70 110 C 70 140, 110 140, 110 110" stroke="3" fill="none"/> <path d="M130 110 C 120 140, 180 140, 170 110" stroke="3" fill="none"/> </svg> ~~~ <br> 曲線效果類似下面這張圖: ![](https://box.kancloud.cn/2e6154086ca5c51409f5f446074cc15e_226x191.png) 可以看到`M`后面的起點,加`C`后面3個點,構成了貝賽爾曲線的`4`個點。 <br> <br> # Canvas 與貝塞爾曲線 ## 二次方貝塞爾曲線 `CanvasRenderingContext2D.quadraticCurveTo()` 是 Canvas 2D API 新增二次貝塞爾曲線路徑的方法。它需要2個點。 第一個點是控制點,第二個點是終點。 起始點是當前路徑最新的點,當創建二次貝賽爾曲線之前,可以使用 `moveTo()` 方法進行改變。 <br> 語法 ~~~ ctx.quadraticCurveTo(cpx, cpy, x, y); ~~~ 參數 * `cpx`:控制點的 x 軸坐標。 * `cpy`:控制點的 y?軸坐標。 * `x`:終點的 x 軸坐標。 * `y`:終點的 y?軸坐標。 ~~~js // 二次貝塞爾曲線 ctx.beginPath(); ctx.moveTo(50, 20); ctx.quadraticCurveTo(230, 30, 50, 100); ctx.stroke(); // 畫起點和終點 ... // 畫控制點 ... ~~~ ![](https://box.kancloud.cn/8e1098b10399f58030564b207d5f9709_301x202.png) <br> ## 三次貝塞爾曲線 `CanvasRenderingContext2D.bezierCurveTo()` 是 Canvas 2D API 繪制三次貝賽爾曲線路徑的方法。 該方法需要三個點。 第一、第二個點是控制點,第三個點是結束點。起始點是當前路徑的最后一個點,繪制貝賽爾曲線前,可以通過調用 `moveTo()` 進行修改。 <br> 語法 ~~~ ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); ~~~ 參數 * `cp1x`:第一個控制點的 x 軸坐標。 * `cp1y`:第一個控制點的 y?軸坐標。 * `cp2x`:第二個控制點的 x 軸坐標。 * `cp2y`:第二個控制點的 y?軸坐標。 * `x`:結束點的 x 軸坐標。 * `y`:結束點的 y?軸坐標。 ~~~js // 定義點 {x, y} let start = { x: 50, y: 20 }; let cp1 = { x: 230, y: 30 }; let cp2 = { x: 150, y: 80 }; let end = { x: 250, y: 100 }; // 畫三次貝塞爾曲線 ctx.beginPath(); ctx.moveTo(start.x, start.y); ctx.bezierCurveTo(cp1.x, cp1.y, cp2.x, cp2.y, end.x, end.y); ctx.stroke(); // 畫起點和終點 ... // 畫控制點 ... ~~~ ![](https://box.kancloud.cn/c8f388fc2617f920a0e50be3435ee0a8_369x205.png) <br> <br> # CSS3動畫與貝塞爾曲線 ## timing-function ` timing-function` CSS 數據類型表示一個數學函數,它描述了在一個過渡或動畫中一維數值的改變速度。這實質上讓你可以自己定義一個加速度曲線,以便動畫的速度在動畫的過程中可以進行改變。這些函數通常被稱為緩動函數。 <br> 這是一個表示時間輸出比率的函數,表示為`<number>`,0, 0 代表初始狀態,1, 1 代表終止狀態。 <br> 輸出比可以大于1.0(或者小于0.0)。這是因為在一種反彈效果中,動畫是可以比最后的狀態走的更遠的,然后再回到最終狀態。 ![](https://box.kancloud.cn/89dba05979647dc9fe4d1fe3d776187c_249x332.png) ![](https://box.kancloud.cn/5df835e727688fe212194123ef6d1c30_249x332.png) <br> 不過,如果輸出值超過了它允許的范圍,比如組成一個顏色的值大于了255或者小于了0,這個值會被修改為允許范圍內的最接近的值(在顏色值這個例子中分別為255和0)。一些貝塞爾曲線展示了這些性質。 <br> ## cubic-bezier屬性 cubic-bezier() 定義了一條 立方貝塞爾曲線(cubic Bézier curve)。這些曲線是連續的,一般用于動畫的平滑變換,也被稱為緩動函數(easing functions)。 <br> 一條立方貝塞爾曲線需要四個點來定義,P0 、P1 、P2 和 P3。P0 和 P3 是起點和終點,這兩個點被作為比例固定在坐標系上,橫軸為時間比例,縱軸為完成狀態。P0 是 (0, 0),表示初始時間和初始狀態。P3 是 (1, 1) ,表示終止時間和終止狀態。 <br> 并非所有的三次貝塞爾曲線都適合作為計時函數,也并非所有的曲線都是數學函數,即給定橫坐標為0或1的曲線。在CSS定義的P0和P3固定的情況下,三次貝塞爾曲線是一個函數,因此,**當且僅當P1和P2的橫坐標都在[0,1]范圍內**時,三次貝塞爾曲線是有效的。 <br> 在[0,1]范圍之外的P1或P2縱坐標的立方貝塞爾曲線可能會產生彈跳效應。 <br> 當您指定無效的cubic-bezier曲線時,CSS會忽略整個屬性。 ### 語法 ~~~ cubic-bezier(x1, y1, x2, y2) ~~~ ***x1*,*y1*,*x2*,*y2*** `<number>`值表示橫坐標,P1和P2點的縱坐標表示三次貝塞爾曲線。 x1和x2必須在[0,1]范圍內,否則該值無效。 ### 實例 ~~~ cubic-bezier(0.1, 0.7, 1.0, 0.1) The canonical Bézier curve with four <number> in the [0,1] range. cubic-bezier(0, 0, 1, 1) Using <integer> is valid as any <integer> is also a <number>. cubic-bezier(-0.2, 0.6, -0.1, 0) Negative values for abscissas are valid, leading to bouncing effects. cubic-bezier(1.1, 0, 4, 0) Values > 1.0 for abscissas are also valid. ~~~ <br> ## 拋物線運動 將拋物線運動分解為水平和垂直方向。 拋物線運動元素使用至少內外兩層標簽,例如,本demo拋物線運動物體是CSS世界這本書的縮略圖,我們可以外面一層`<div>`,里面是`<img>`圖片: ~~~ <div class="fly-item"> <img src="./book.jpg"> </div> ~~~ 然后內外兩次標簽一個負責水平方向的translate移動,一個負責垂直方向的translate移動,然后使用不同的緩動函數,也就是使用不同的`timing-function`,在CSS3`animation`動畫效果中是`animation-timing-function`屬性,在CSS3`transition`過渡效果中是`transition-timing-function`屬性。CSS代碼如下: ~~~ .fly-item { /* 水平移動,線性勻速 */ transition-timing-function: linear; } .fly-item > img { /* 垂直移動,先慢后快 */ transition-timing-function: cubic-bezier(.55,0,.85,.36); } ~~~ 然后同時執行`translate`移動,拋物線效果就出現了。 <br> <br> # 工具 http://cubic-bezier.com/ ![](https://box.kancloud.cn/cd57302fec2542049b7afda670d94c84_431x422.png) x軸表示隨著時間勻速前進,y軸表示隨著時間推移運動距離的百分比,x y的最大值都為 1 <br> <br> # 參考資料 [貝塞爾曲線與CSS3動畫、SVG和canvas的基情](https://www.zhangxinxu.com/wordpress/2013/08/%E8%B4%9D%E5%A1%9E%E5%B0%94%E6%9B%B2%E7%BA%BF-cubic-bezier-css3%E5%8A%A8%E7%94%BB-svg-canvas/) [貝塞爾曲線掃盲](http://www.html-js.com/article/1628) [【干貨滿滿】貝塞爾曲線(Bézier curve)——什么神仙操作](https://juejin.im/post/5be99bf66fb9a049db72a956) [這回試試使用CSS實現拋物線運動效果](https://www.zhangxinxu.com/wordpress/2018/08/css-css3-%E6%8A%9B%E7%89%A9%E7%BA%BF%E5%8A%A8%E7%94%BB/) [深入理解貝塞爾曲線](https://juejin.im/post/5b854e1451882542fe28a53d) [MDN - timing function](https://developer.mozilla.org/zh-CN/docs/Web/CSS/timing-function) [MDN - quadratic?CurveTo](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/quadraticCurveTo) [MDN - bezierCurveTo](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/bezierCurveTo)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看