Почему мой холст JavaScript не создает связанных линий? - PullRequest
1 голос
/ 20 мая 2011

Я пытаюсь создать сценарий холста, который визуально рисует кубическую кривую Безье, но до сих пор мне не удалось соединить мои линии.Смотрите код здесь

 var canvas=document.getElementById("canvas");
 var c = canvas.getContext("2d");  
  // Bezier eq. code
 coord = function(x,y) { if(!x) var x=0; if(!y) var y=0; return {x: x, y: y}; }

B1 = function(t) { return (t*t*t); }
B2 = function(t) { return (3*t*t*(1-t)); } 
B3 = function(t) { return (3*t*(1-t)*(1-t)); }
B4 = function(t) { return ((1-t)*(1-t)*(1-t)); }

function getBezier(t,C1,C2,C3,C4) {
    var pos = new coord();
    pos.x = C1.x * B1(t) + C2.x * B2(t) +C3.x * B3(t) + C4.x * B4(t);
    pos.y = C1.y * B1(t) + C2.y * B2(t) + C3.y * B3(t) + C4.y * B4(t);
    return pos; 
}
//Ctrl points.
P1 = coord(12,12);
P2 = coord(90,1);
P3 = coord(0,190);
P4 = coord(150,150);


t=0;
function drawbez() {
  if (t == 0) {var interval = setInterval('drawbez()',1);}
  var curpos = getBezier(t2,P1,P2,P3,P4); // Staðan í ferlinum
  if (t > 1) { clearInterval(interval); return; }
  c2.moveTo(curpos.x,curpos.y);
  c2.lineTo(curpos.x+t2,curpos.y+t2);
  c2.stroke();
  t = t+0.01
 }

Любые идеи?

Я сделал код, используя случайные числа, используя точно такие же команды рисования, и это фактически дало мне соединенные линии.

См.код на HTML здесь

Использование учебника по кривым Безье из 13-й параллели http://13thparallel.com/archive/bezier-curves/

Ответы [ 3 ]

1 голос
/ 20 мая 2011

Эй, я заставил его работать, изменив код на следующий:

var canvas = document.getElementById("canvas");
var c = canvas.getContext("2d");
// Bezier eq. code
coord = function(x, y) {
    if (!x) {
        x = 0;
    }
    if (!y) {
        y = 0;
    }
    return {
        x: x,
        y: y
    };
};

B1 = function(t) {
    return (t * t * t);
};
B2 = function(t) {
    return (3 * t * t * (1 - t));
};
B3 = function(t) {
    return (3 * t * (1 - t) * (1 - t));
};
B4 = function(t) {
    return ((1 - t) * (1 - t) * (1 - t));
};

function getBezier(t, C1, C2, C3, C4) {
    var pos = new coord();
    pos.x = C1.x * B1(t) + C2.x * B2(t) + C3.x * B3(t) + C4.x * B4(t);
    pos.y = C1.y * B1(t) + C2.y * B2(t) + C3.y * B3(t) + C4.y * B4(t);
    return pos;
}
//Ctrl points.
P1 = coord(12, 12);
P2 = coord(90, 1);
P3 = coord(0, 190);
P4 = coord(150, 150);

t = 0;

var drawbez = function() {
    var interval;
    if (t === 0) {
        interval = setInterval(drawbez, 1);
    }
    var curpos = getBezier(t, P1, P2, P3, P4); // Staðan í ferlinum
    if (t > 1) {
        if (interval) {
            clearInterval(interval);
        }
        return;
    }
    //c.moveTo(curpos.x, curpos.y);
    c.lineTo(curpos.x + t, curpos.y + t);
    c.stroke();
    t = t + 0.01;
};

drawbez();

Пожалуйста, посмотрите эту скрипку для рабочего примера.

По сути, t2 никогда не объявлялся, interval находился вне области видимости, ссылка setTimeout() на drawbez, казалось, находилась вне области видимости (возможно, потому что вы указали имя строковой функции, а не прямую ссылку на объект ) и удаление .moveTo(), как упомянуто в ответе Джона Грина, дало гораздо более плавную строку.

0 голосов
/ 20 мая 2011

Ваша логика была не совсем правильной.Ваш код постоянно рисует линию от curpos до curpos + t2, которая всегда переходила в крошечную линию, если t2 всегда меньше единицы, прежде чем вызывать clearinterval.Я адаптировал ваш код ниже, который хранит prevcoord и рисует линию от предыдущей координаты до новой координаты каждый раз, когда вызывается drawBez.

Если вы собираетесь делать эффективную анимацию на холсте, это определенноне лучший путь к этому.Попробуйте поискать лучшие практики по созданию потока анимации (отозвать обновление и т. Д.).

 var canva2s=document.getElementById("canvas2");
    var c2 = canvas2.getContext("2d");
    c2.lineWidth = 1;
    // Bezier jafna sett inn
    coord = function(x,y) {
        if(!x) var x=0;
        if(!y) var y=0;
        return {
            x: x,
            y: y
        };
    }

    B1 = function(t) {
        return (t*t*t);
    }
    B2 = function(t) {
        return (3*t*t*(1-t));
    } 
    B3 = function(t) {
        return (3*t*(1-t)*(1-t));
    }
    B4 = function(t) {
        return ((1-t)*(1-t)*(1-t));
    }

    function getBezier(t,C1,C2,C3,C4) {
        var pos = new coord();
        pos.x = C1.x * B1(t) + C2.x * B2(t) +C3.x * B3(t) + C4.x * B4(t);
        pos.y = C1.y * B1(t) + C2.y * B2(t) + C3.y * B3(t) + C4.y * B4(t);
        return pos;
    }
    //Stýripunktar
    P1 = coord(12,12);
    P2 = coord(90,1);
    P3 = coord(0,190);
    P4 = coord(150,150);

    //var newpos = getBezier(0.2,P1,P2,P3,P4);
    t2=0;
    var prevCoord = null;
    //dir=0;
    function drawbez() {
        if (t2 == 0) {
            var interval = setInterval('drawbez()',1);
        }        
        var curpos = getBezier(t2,P1,P2,P3,P4); // Staðan í ferlinum        
        if (t2 > 1) {
            clearInterval(interval);
            return;
        }        
        if(prevCoord != null){
            c2.moveTo(prevCoord.x,prevCoord.y);
            c2.lineTo(curpos.x,curpos.y);
            c2.stroke();
        }        
        prevCoord = curpos;            
        t2 = t2+0.01;
    }
0 голосов
/ 20 мая 2011

Я думаю, что у вас есть большие проблемы с вашим Безье (lineTo вместо bezierCurveTo или даже quadraticCurveTo), но отключенные линии, потому что вы перемещаете курсор между рисованиями. Закомментируйте эту строку:

  c2.moveTo(curpos.x,curpos.y);

Или, возможно, более точно:

  c2.lineTo(curpos.x, curpos.y);  // remove the moveTo.

И, частично, потому что кто-то обвинил меня (справедливо) в том, что я раньше понтифицировал ... Я не рекомендую Canvas для рисования кривых. Фундаментальная архитектура является полностью процедурной, что может означать, что тысячи чертежей DOM требуют даже очень простых изображений. С SVG обычно лучше работать, если вам не нужны аффинные матрицы изображений для псевдо 3D или что-то в этом роде.

...