Рисование плавных линий холстом - PullRequest
4 голосов
/ 25 октября 2011

Пока что ни одна из нитей на плавных линиях не верна.

Как нарисовать гладкую кривую через N точек, используя JavaScript-холст HTML5?

Сглаженные пользовательские линии на холсте

Оба результата приводят к неровным линиям. Под сглаживанием я подразумеваю использование точек x, y в качестве контрольных точек, чтобы сделать линию гладкой. Линия не должна проходить через точки. Он просто должен нарисовать плавную линию с учетом n точек.

По сути, я записываю каждый отрезок, затем, когда пользователь подведет курсор, он сгладит линию.

Я попробовал свой собственный метод, используя bezierCurveTo, но он только сглаживает все остальные точки, а затем точки соединения остаются жесткими. Интернет, кажется, думает, что я ищу, называется кривыми B-сплайна. Я попытался применить матрицу линейной алгебры к задаче, но мне это не удалось.

Вот лучшая кривая, которую я могу получить, (изображение). Красная линия - это «сглаженная» линия, поскольку вы можете видеть, что она сглаживает любую другую точку, но не непрерывную. Это использует код из

Как нарисовать гладкую кривую через N точек, используя JavaScript-холст HTML5?

Мой код делает то же самое

http://www.square -bracket.com / изображения / smoothlines.png

Спасибо за вашу помощь!

Ответы [ 2 ]

3 голосов
/ 25 октября 2011

Вы должны держать ту же касательную в точках ниже на линии. Чек http://jsfiddle.net/FHKuf/4/.

Edit:

Извините, только что заметил ваш комментарий сегодня. Просто случилось что-то связанное и вспомнил твой вопрос. Бывает, что в прошлом я писал код для интерполяции строк. Он называется Catmull-Rom (просто ссылка, которую я гуглил), он проходит мимо средних контрольных точек. Я изменил код в своем тесте и подумал, что вам это может пригодиться. Смотрите на http://jsfiddle.net/FHKuf/6/.

0 голосов
/ 28 июня 2017

Я изучал все техники, но не нашел правильного решения для плавного свободного рисования на холсте. Тогда я просто использовал quadraticCurveTo с другой логикой, не используя оригинальные точки мыши.

Сначала я рассчитал контрольную точку (среднюю точку) и заменил старую точку перемещения мыши контрольной точкой. Я сделал это 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 = [];
...