前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[前端]使用曲线将多点连成一条平滑的曲线

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

作者头像
Tuzei
发布2020-03-16 17:00:09
1.5K0
发布2020-03-16 17:00:09
举报
文章被收录于专栏:Tuzei的笔记Tuzei的笔记

之前在写一个项目需要把多点连成平滑的曲线,而且这些点是无法预知的。开始想到用贝塞尔曲线,但是具体贝塞尔曲线的控制点要怎么设定,怎样让多点都落在曲线上而且保持曲线的平滑,就一直没想到。 后来参考了一篇《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();
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档