基於canvas使用貝塞爾曲線平滑擬合折線段

2021-08-13 08:17:20 字數 2111 閱讀 3519

本次分享一下在canvas中將繪製出來的折線段的稜角「磨平」,也就是通過貝塞爾曲線穿過各個描點來代替原有的折線圖。

歡迎關注我的部落格,不定期更新中——

先來看下echarts下折線圖的渲染效果:

一開始我沒注意到其實這個折線段是曲線穿過去的,只認為是單純的描點繪圖,所以起初我實現的「簡(醜)易(陋)」版本是這樣的:

不要關注樣式,重點就是實現之後才發現看起來人家echarts的實現描點非常的圓滑,也由此引發了之後的**。怎麼有規律的畫平滑曲線?

先來看下最終模仿的實現:

因為我也不知道echarts內部怎麼實現的(逃

看起來已經非常圓潤了,和我們最初的設想十分接近了。再看下曲線是否穿過了描點:

好的!結果很明顯現在來重新看下我們的實現方式。

模擬資料

var data = [math.random() * 300];

for (var i = 1; i < 50; i++)

option = ,

series: ,

areastyle: ,

data: data}};

繪製折線圖

首先初始化乙個建構函式來放置需要用到的資料:

function

lineargradient

(option)

繪製折線圖:

上面的公式涉及到四個座標點,當前點,前乙個點以及後兩個點,而當座標值為下圖展示的時候繪製出來的曲線如下所示:

所以在將折線換成平滑曲線的時候,將邊界值以及其他控制點計算好之後代入到貝塞爾函式中就完成了:

//核心實現

this.series.data.foreach(function

(item, index) else

if(index ===1) else

if(index === self.series.data.length - 1)

self.ctx.beziercurveto(cax, cay, cbx, cby, nowx, nowy);

//繪製出上乙個點到當前點的貝塞爾曲線

})

由於我每次遍歷的點都是當前點,但是文章中給出的公式是計算會知道下乙個點的控制點演算法,故在**實現中我將所有點的計算挪前了一位。當index = 0時也就是初始點是不需要曲線繪製的,因為我們繪製的是從前乙個點到當前點的曲線,沒有到0的曲線需要繪製。從index = 1開始我們就可以正常開始繪製,從0到1的曲線,由於index = 1時是沒有在他前面第二個點的故其屬於邊界值點,也就是需要特殊進行計算,以及最後乙個點。其餘均按照正常公式算出ab的xy座標代入貝塞爾函式即可。

源**見這裡

慣例po作者的部落格,不定時更新中——

有問題歡迎在issues下交流。

使用canvas繪製貝塞爾曲線

1 二次貝塞爾曲線 quadraticcurveto cpx,cpy,x,y cpx,cpy表示控制點的座標,x,y表示終點座標 數學公式表示如下 二次方貝茲曲線的路徑由給定點p0 p1 p2的函式b t 追蹤 例項 複製 如下 canvas直線 效果 2 三次貝塞爾曲線 beziercurveto...

canvas效果案例 貝塞爾曲線

繪製二次貝塞爾曲線 ctx.quadraticcurveto x1,y1,x,y 從上一點開始繪製一條二次曲線,到 x,y 為止,並且以 x1,y1 作為控制點 ctx.beginpath ctx.strokestyle green ctx.linewidth 4 起始點 ctx.moveto 10...

貝塞爾曲線使用

貝塞爾曲線數學公式 1。兩個控制點 線性公式 x 1 t x0 t x1 0 t 1 y 1 t y0 t y1 0 t 1 2.三個控制點 二次公式 x 1 t 1 t x0 2 t 1 t x1 t t x2 0 t 1 y 1 t 1 t y0 2 t 1 t y1 t t y2 0 t 1 ...