[前端]使用曲线将多点连成一条平滑的曲线

2020-03-16 17:00:09 浏览数 (1)

之前在写一个项目需要把多点连成平滑的曲线,而且这些点是无法预知的。开始想到用贝塞尔曲线,但是具体贝塞尔曲线的控制点要怎么设定,怎样让多点都落在曲线上而且保持曲线的平滑,就一直没想到。 后来参考了一篇《Android 使用贝塞尔曲线将多点连成一条平滑的曲线》的博文,地址:http://m.blog.csdn.net/article/details?id=52667896 写得挺好的,不过没太仔细研究 原代码是java的,然后就直接用原代码改成了js版本的(虽然最后用了其他方式来实现……不过这个如果做什么在线生成图表什么的可以用上)

效果:

Paste_Image.png

后面的点契合的挺好的

代码:

代码语言:javascript复制
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<mPointList.length;i  ){
    ctx.beginPath();
    ctx.arc(mPointList[i].x,mPointList[i].y,5,0,Math.PI*2,true);
    ctx.closePath();
    ctx.fill();
}

0 人点赞