1.前言
canvas將多個(gè)點(diǎn)連接成線,最主要還是用于使用鼠標(biāo)繪畫(huà)之類(lèi)的用途,但是我們往往會(huì)發(fā)現(xiàn)使用這些點(diǎn)連接起來(lái)的線非常不規(guī)整,很不自然
所以大多數(shù)人想到優(yōu)化這一點(diǎn)的方法應(yīng)該就是將簡(jiǎn)單的點(diǎn)與點(diǎn)的直線連接改為帶一定曲度的曲線
2.參考
帶著目的我在網(wǎng)上查找相應(yīng)的文章然后找到了這個(gè)博客
但是這個(gè)博客不早知道是沒(méi)講清楚還是寫(xiě)錯(cuò)了,你是沒(méi)辦法直接使用他的方法的,里面有些參數(shù)不清楚,而且因?yàn)樘玫木壒世锩娴逆溄佣际Я?br>
所以我在網(wǎng)上搜索了里面提供的關(guān)鍵字:貝塞爾曲線控制點(diǎn)確定的方法.doc 百度文庫(kù)里有
根據(jù)里面的秒速完善了方法
getCtrlPoint(ps, i, a, b){
if(!a||!b){
a=0.25;
b=0.25;
}
let p_1 = ps[i-1],p = ps[i],p1 = ps[i+1],p2 = ps[i+2];
if(typeof p_1 != 'number'){
p_1 = p;
}
if(typeof p1 != 'number'){
p1 = p;
}
if(typeof p2 != 'number'){
p2 = p;
}
var pAx = p[0] + (p1[0] - p_1[0])*a;
var pAy = p[1] + (p1[1] - p_1[1])*a;
var pBx = p1[0] + (p2[0] - p[0])*b;
var pBy = p1[1] + (p2[1] - p[1])*b;
return {
pA:{x:pAx,y:pAy},
pB:{x:pBx,y:pBy}
}
}
第一個(gè)點(diǎn)和最后兩個(gè)點(diǎn)的算法文檔里面有說(shuō)明我就不多說(shuō)了
3.結(jié)果
context(){//canvas對(duì)象
return canvas.getContext("2d");
},
根據(jù)方法使用曲線畫(huà)線方法劃線
//index表示當(dāng)前畫(huà)的是第幾個(gè)點(diǎn) for循環(huán)里的參數(shù)
var ctrlP = this.getCtrlPoint(points,index);
//這里坐標(biāo)減0.5是為了能讓線寬1px的線能顯示正常
this.context.bezierCurveTo(ctrlP.pA.x - 0.5, ctrlP.pA.y - 0.5, ctrlP.pB.x - 0.5,ctrlP.pB.y -0.5, point[0] - 0.5, point[1] - 0.5);
這里將直線改為曲線算成功了,但是我發(fā)現(xiàn)直接使用鼠標(biāo)畫(huà)的線依然很難看不自熱,這是因?yàn)槭髽?biāo)劃線點(diǎn)過(guò)于密集的原因,可以在劃線時(shí)間隔曲線將圖形模糊處理
//這個(gè)loop方法是我寫(xiě)的,你們可以使用forEach,只需要注意里面的this變量就行
//fuzzy這個(gè)變量表示當(dāng)前點(diǎn)是它的整倍數(shù)時(shí)才計(jì)入劃線點(diǎn),當(dāng)然這個(gè)數(shù)字不能太大不然會(huì)失真
points.loop(this,function(point,index){
if(index%fuzzy == 0){
var ctrlP = this.getCtrlPoint(points,index);
this.context.bezierCurveTo(ctrlP.pA.x - 0.5, ctrlP.pA.y - 0.5, ctrlP.pB.x - 0.5,ctrlP.pB.y -0.5, point[0] - 0.5, point[1] - 0.5);
}
});
老實(shí)說(shuō)感覺(jué)還是畫(huà)出來(lái)的線比原來(lái)是好點(diǎn),但是還是不自然的樣子