之前在寫一個(gè)項(xiàng)目需要把多點(diǎn)連成平滑的曲線,而且這些點(diǎn)是無(wú)法預(yù)知的。開(kāi)始想到用貝塞爾曲線,但是具體貝塞爾曲線的控制點(diǎn)要怎么設(shè)定,怎樣讓多點(diǎn)都落在曲線上而且保持曲線的平滑,就一直沒(méi)想到。
后來(lái)參考了一篇《Android 使用貝塞爾曲線將多點(diǎn)連成一條平滑的曲線》的博文,地址:http://m.blog.csdn.net/article/details?id=52667896
寫得挺好的,不過(guò)沒(méi)太仔細(xì)研究
原代碼是java的,然后就直接用原代碼改成了js版本的(雖然最后用了其他方式來(lái)實(shí)現(xiàn)……不過(guò)這個(gè)如果做什么在線生成圖表什么的可以用上)
效果:

Paste_Image.png
后面的點(diǎn)契合的挺好的
代碼:
var mPointList = [{x:10,y:10},{x:120,y:40},{x:260,y:180},{x:380,y:40},{x:420,y:120},
{x:510,y:110},{x:620,y:140},{x:760,y:280},{x:880,y:240},{x:920,y:120}];
var lineSmoothness = 0.16;
measurePath(mPointList,lineSmoothness);
function measurePath(mPointList,lineSmoothness) {
var prePreviousPointX ;
var prePreviousPointY ;
var previousPointX ;
var previousPointY ;
var currentPointX ;
var currentPointY ;
var nextPointX;
var nextPointY;
var lineSize = mPointList.length;
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.strokeStyle="#FF0000";
ctx.beginPath();
for (var valueIndex = 0; valueIndex < lineSize; ++valueIndex) {
if (currentPointX) {
var point = mPointList[valueIndex];
currentPointX = point.x;
currentPointY = point.y;
}
if (previousPointX) {
//是否是第一個(gè)點(diǎn)
if (valueIndex > 0) {
var point = mPointList[valueIndex-1];
previousPointX = point.x;
previousPointY = point.y;
} else {
//是的話就用當(dāng)前點(diǎn)表示上一個(gè)點(diǎn)
previousPointX = currentPointX;
previousPointY = currentPointY;
}
}
if (prePreviousPointX) {
//是否是前兩個(gè)點(diǎn)
if (valueIndex > 1) {
var point = mPointList[valueIndex-2];
prePreviousPointX = point.x;
prePreviousPointY = point.y;
} else {
//是的話就用當(dāng)前點(diǎn)表示上上個(gè)點(diǎn)
prePreviousPointX = previousPointX;
prePreviousPointY = previousPointY;
}
}
// 判斷是不是最后一個(gè)點(diǎn)了
if (valueIndex < lineSize - 1) {
var point = mPointList[valueIndex+1];
nextPointX = point.x;
nextPointY = point.y;
} else {
//是的話就用當(dāng)前點(diǎn)表示下一個(gè)點(diǎn)
nextPointX = currentPointX;
nextPointY = currentPointY;
}
if (valueIndex == 0) {
// 將Path移動(dòng)到開(kāi)始點(diǎn)
ctx.moveTo(mPointList[0].x,mPointList[0].y);
} else {
// 求出控制點(diǎn)坐標(biāo)
var firstDiffX = (currentPointX - prePreviousPointX);
var firstDiffY = (currentPointY - prePreviousPointY);
var secondDiffX = (nextPointX - previousPointX);
var secondDiffY = (nextPointY - previousPointY);
var firstControlPointX = previousPointX + (lineSmoothness * firstDiffX);
var firstControlPointY = previousPointY + (lineSmoothness * firstDiffY);
var secondControlPointX = currentPointX - (lineSmoothness * secondDiffX);
var secondControlPointY = currentPointY - (lineSmoothness * secondDiffY);
//畫(huà)出曲線
ctx.bezierCurveTo(firstControlPointX, firstControlPointY, secondControlPointX, secondControlPointY,
currentPointX, currentPointY);
}
// 更新值,
prePreviousPointX = previousPointX;
prePreviousPointY = previousPointY;
previousPointX = currentPointX;
previousPointY = currentPointY;
currentPointX = nextPointX;
currentPointY = nextPointY;
}
ctx.stroke();
}
//畫(huà)點(diǎn)
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.fillStyle="#000";
for (var i=0;i<mPointList.length;i++){
ctx.beginPath();
ctx.arc(mPointList[i].x,mPointList[i].y,5,0,Math.PI*2,true);
ctx.closePath();
ctx.fill();
}