之前在写一个项目需要把多点连成平滑的曲线,而且这些点是无法预知的。开始想到用贝塞尔曲线,但是具体贝塞尔曲线的控制点要怎么设定,怎样让多点都落在曲线上而且保持曲线的平滑,就一直没想到。
后来参考了一篇《Android 使用贝塞尔曲线将多点连成一条平滑的曲线》的博文,地址:http://m.blog.csdn.net/article/details?id=52667896
写得挺好的,不过没太仔细研究
原代码是java的,然后就直接用原代码改成了js版本的(虽然最后用了其他方式来实现……不过这个如果做什么在线生成图表什么的可以用上)
效果:
Paste_Image.png
后面的点契合的挺好的
代码:
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) {
//是否是第一个点
if (valueIndex > 0) {
var point = mPointList[valueIndex-1];
previousPointX = point.x;
previousPointY = point.y;
} else {
//是的话就用当前点表示上一个点
previousPointX = currentPointX;
previousPointY = currentPointY;
}
}
if (prePreviousPointX) {
//是否是前两个点
if (valueIndex > 1) {
var point = mPointList[valueIndex-2];
prePreviousPointX = point.x;
prePreviousPointY = point.y;
} else {
//是的话就用当前点表示上上个点
prePreviousPointX = previousPointX;
prePreviousPointY = previousPointY;
}
}
// 判断是不是最后一个点了
if (valueIndex < lineSize - 1) {
var point = mPointList[valueIndex+1];
nextPointX = point.x;
nextPointY = point.y;
} else {
//是的话就用当前点表示下一个点
nextPointX = currentPointX;
nextPointY = currentPointY;
}
if (valueIndex == 0) {
// 将Path移动到开始点
ctx.moveTo(mPointList[0].x,mPointList[0].y);
} else {
// 求出控制点坐标
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);
//画出曲线
ctx.bezierCurveTo(firstControlPointX, firstControlPointY, secondControlPointX, secondControlPointY,
currentPointX, currentPointY);
}
// 更新值,
prePreviousPointX = previousPointX;
prePreviousPointY = previousPointY;
previousPointX = currentPointX;
previousPointY = currentPointY;
currentPointX = nextPointX;
currentPointY = nextPointY;
}
ctx.stroke();
}
//画点
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.fillStyle="#000";
for (var i=0;i
ctx.beginPath();
ctx.arc(mPointList[i].x,mPointList[i].y,5,0,Math.PI*2,true);
ctx.closePath();
ctx.fill();
}