用帆布画流畅的线条

Drawing smooth lines with canvas

本文关键字:帆布      更新时间:2023-09-26

到目前为止,这里没有一个线程是正确的。

如何通过使用javascript HTML5画布N点绘制平滑曲线?

平滑用户在画布上绘制的线条

都产生锯齿状的线条。平滑是指使用x,y点作为控制点使直线平滑。直线不需要经过这些点。它只需要在给定n个点的情况下画一条平滑的线。

基本上我是记录每一个线段,然后当用户鼠标向上,它会平滑的线。

我已经尝试了我自己的方法,使用bezierCurveTo,但它只平滑了所有其他点,然后连接点仍然很粗糙。网上似乎认为我要找的是b样条曲线。我试着用线性代数矩阵来解决这个问题,但是我失败了,哈哈。

这是我能得到的最好的曲线,(图片)。红色的线是"平滑"的线,正如你所看到的,它平滑了所有其他点,但不是连续的。这是使用

中的代码

如何通过使用javascript HTML5画布N点绘制平滑曲线?

我的代码做同样的事情

http://www.square-bracket.com/images/smoothlines.png

谢谢你的帮助!

你需要保持相同的切线在下面的点。检查http://jsfiddle.net/FHKuf/4/。

编辑:

对不起,今天才注意到你的评论。只是碰巧在测试一些相关的东西,想起了你的问题。在过去,我确实编写了一些代码来插入一些行。它被称为Catmull-Rom(只是一个参考,我谷歌),它通过中间控制点。我确实更改了我的测试代码,并认为您可能会用到它。

我正在探索所有的技术,但没有得到任何适当的解决方案在画布上流畅的自由绘图。然后我简单地使用二次曲线与不同的逻辑,没有使用原来的鼠标点。

我首先计算控制点(中点),并用控制点替换旧的鼠标移动点。我这样做了2次,最后对最后的数组应用了quadraticCurveTo,我得到了超级光滑的绘图。

这是惊人的。我没有使用这个笨重的paper.js和其他平滑库。

下面是我的代码:
currentCanvas.beginPath();
        currentCanvas.lineCap = 'round';
        currentCanvas.strokeStyle = "black";
        currentCanvas.lineWidth = "2";
        currentCanvas.moveTo(queue[0].x, queue[0].y);
        //queue is an array of original points which were stored while onmousemove event callback
        var tempQueue1 = [queue[0]];
        for (var i = 1; i < queue.length - 1;  i = i+1) {
            //if((Math.abs(queue[i].x - queue[i-1].x) >3 || Math.abs(queue[i].x - queue[i-1].x)<1) &&  (Math.abs(queue[i].y - queue[i-1].y) >3 || Math.abs(queue[i].y - queue[i-1].y)<1)){
                var c = (queue[i].x + queue[i + 1].x) / 2;
                var d = (queue[i].y + queue[i + 1].y) / 2;
                //tempQueue.push(queue[i]);
                tempQueue1.push({x:c, y:d});
                //currentCanvas.quadraticCurveTo(queue[i].x, queue[i].y, c, d);
            //}
        }
        var tempQueue2 = [tempQueue1[0]];
        for (var i = 1; i < tempQueue1.length - 1;  i = i+1) {
            //if((Math.abs(queue[i].x - queue[i-1].x) >3 || Math.abs(queue[i].x - queue[i-1].x)<1) &&  (Math.abs(queue[i].y - queue[i-1].y) >3 || Math.abs(queue[i].y - queue[i-1].y)<1)){
                var c = (tempQueue1[i].x + tempQueue1[i + 1].x) / 2;
                var d = (tempQueue1[i].y + tempQueue1[i + 1].y) / 2;
                //tempQueue.push(queue[i]);
                tempQueue2.push({x:c, y:d});
                //currentCanvas.quadraticCurveTo(queue[i].x, queue[i].y, c, d);
            //}
        }
        var tempQueue = [tempQueue2[0]];
        for (var i = 1; i < tempQueue2.length - 1;  i = i+1) {
            //if((Math.abs(queue[i].x - queue[i-1].x) >3 || Math.abs(queue[i].x - queue[i-1].x)<1) &&  (Math.abs(queue[i].y - queue[i-1].y) >3 || Math.abs(queue[i].y - queue[i-1].y)<1)){
                var c = (tempQueue2[i].x + tempQueue2[i + 1].x) / 2;
                var d = (tempQueue2[i].y + tempQueue2[i + 1].y) / 2;
                //tempQueue.push(queue[i]);
                tempQueue.push({x:c, y:d});
                //currentCanvas.quadraticCurveTo(queue[i].x, queue[i].y, c, d);
            //}
        }
        for (var i = 1; i < tempQueue.length - 2;  i = i+1) {
            //if((Math.abs(queue[i].x - queue[i-1].x) >3 || Math.abs(queue[i].x - queue[i-1].x)<1) &&  (Math.abs(queue[i].y - queue[i-1].y) >3 || Math.abs(queue[i].y - queue[i-1].y)<1)){
                var c = (tempQueue[i].x + tempQueue[i + 1].x) / 2;
                var d = (tempQueue[i].y + tempQueue[i + 1].y) / 2;
                currentCanvas.quadraticCurveTo(tempQueue[i].x, tempQueue[i].y, c, d);
            //}
        }
        // For the last 2 points
        currentCanvas.quadraticCurveTo(
        tempQueue[i].x,
        tempQueue[i].y,
        tempQueue[i+1].x,
        tempQueue[i+1].y
        );
        currentCanvas.stroke();
        queue = [];

@Manoj Verma使用线点作为控制点的好主意!我对你的代码做了一些改进。仍然很平滑,没有不必要的操作。我还修复了绘图到最后一点的错误

        currentCanvas.beginPath();
        currentCanvas.lineCap = 'round';
        currentCanvas.strokeStyle = "black";
        currentCanvas.lineWidth = 2;
        currentCanvas.moveTo(queue[0].x, queue[0].y);
        let x, y
        for (let i = 0; i < queue.length - 1; i++) {
            x = (queue[i].x + queue[i + 1].x) / 2;
            y = (queue[i].y + queue[i + 1].y) / 2;
            currentCanvas.quadraticCurveTo(queue[i].x, queue[i].y, x, y);
        }
        const lastPoint = queue[queue.length - 1]
        currentCanvas.quadraticCurveTo(lastPoint.x, lastPoint.y, lastPoint.x, lastPoint.y)
        currentCanvas.stroke();