为什么我的画布javascript没有连接线?
我试图创建一个画布脚本,直观地绘制一个三次贝塞尔曲线,但到目前为止,我一直没有成功地使我的线连接。请参见此处的代码为什么我的画布javascript没有连接线?,javascript,canvas,bezier,Javascript,Canvas,Bezier,我试图创建一个画布脚本,直观地绘制一个三次贝塞尔曲线,但到目前为止,我一直没有成功地使我的线连接。请参见此处的代码 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 = fu
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上的代码
使用贝塞尔曲线教程
我认为您的贝塞尔曲线存在一些更大的问题(lineTo而不是bezierCurveTo,甚至是QuadicialCurveTo),但断开的线是因为您在绘图之间移动光标。注释掉这一行:
c2.moveTo(curpos.x,curpos.y);
或者更准确地说:
c2.lineTo(curpos.x, curpos.y); // remove the moveTo.
而且,部分原因是有人指责我(正确地说)早些时候高谈阔论。。。我不推荐使用画布绘制曲线。基本的体系结构是完全程序化的,这意味着即使是非常简单的图像,也需要数千个DOM绘图调用。SVG通常更好地使用,除非您需要仿射图像矩阵用于伪3D或类似的东西。我认为您的bezier存在一些更大的问题(lineTo而不是bezier CurveTo,甚至是Quadicial CurveTo),但断开的线是因为您在绘图之间移动光标。注释掉这一行:
c2.moveTo(curpos.x,curpos.y);
或者更准确地说:
c2.lineTo(curpos.x, curpos.y); // remove the moveTo.
而且,部分原因是有人指责我(正确地说)早些时候高谈阔论。。。我不推荐使用画布绘制曲线。基本的体系结构是完全程序化的,这意味着即使是非常简单的图像,也需要数千个DOM绘图调用。SVG通常更好地使用,除非您需要仿射图像矩阵用于伪3D或类似的东西。嘿,我通过将代码更改为以下内容来实现它:
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
超出了范围,对drawbez
的reference似乎超出了范围(可能是因为您指定了字符串函数名而不是直接对象引用),并且删除了.moveTo()
正如约翰·格林在回答中提到的那样,给出了一条更加流畅的线。嘿,我通过将您的代码更改为以下内容来实现这一点:
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
超出了范围,对drawbez
的reference似乎超出了范围(可能是因为您指定了字符串函数名而不是直接对象引用),并且删除了.moveTo()
正如约翰·格林在回答中提到的那样,给出了一条更加流畅的线。你的逻辑不太正确。您的代码不断地从curpos到curpos+t2画一条线,这条线总是指向一条很小的线,因为在调用clearinterval之前,t2总是在一条线之下。我已经修改了下面的代码,它存储了prevcoord,并在每次调用drawBez时从以前的coord到新的coord绘制一条线
如果你想在画布上制作有效的动画,这绝对不是最好的方法。尝试搜索创建动画流的最佳实践(绘制更新调用等)
你的逻辑不太正确。您的代码不断地从curpos到curpos+t2画一条线,这条线总是指向一条很小的线,因为在调用clearinterval之前,t2总是在一条线之下。我已经修改了下面的代码,它存储了prevcoord,并在每次调用drawBez时从以前的coord到新的coord绘制一条线
如果你想在画布上制作有效的动画,这绝对不是最好的方法。尝试搜索创建动画流的最佳实践(绘制更新调用等)
速记。。。间隔仍然超出范围。它应该是全局的,因为每次回来时都会检查它。@John-很好,是的,它应该在drawbez()函数之外声明。
函数。:)速记。。。间隔仍然超出范围。它应该是全局的,因为每次回来时都会检查它。@John-很好,是的,它应该在drawbez()函数之外声明。
函数。:)