Javascript 在html画布上绘制bezier曲线
我需要画一条贝塞尔曲线,它由存储在数组中的N个控制点定义。我有一张500像素x 500像素的画布。 这里是JSFiddle链接:JSFiddle.net/HswXy 整个JS代码:Javascript 在html画布上绘制bezier曲线,javascript,html5-canvas,bezier,Javascript,Html5 Canvas,Bezier,我需要画一条贝塞尔曲线,它由存储在数组中的N个控制点定义。我有一张500像素x 500像素的画布。 这里是JSFiddle链接:JSFiddle.net/HswXy 整个JS代码: <script> window.onload=function(){ var old_n=0,n=0; var nrSelect = document.getElementById("mySelect"); var submit = document
<script>
window.onload=function(){
var old_n=0,n=0;
var nrSelect = document.getElementById("mySelect");
var submit = document.getElementById("submit");
nrSelect.addEventListener("change",function(){
old_n=n;
n = nrSelect.selectedIndex;
var inputx,inputy,br;
if(document.getElementById("pointsdiv"))
{
for(i=1;i<=n;i++){
inputx = document.createElement('input');
inputy = document.createElement('input');
br = document.createElement('br');
inputx.type = "text";
inputy.type = "text";
inputx.size = 3;
inputy.size = 3;
inputx.id = "x_" + i;
inputy.id = "y_" + i;
inputx.value = "x_" + i;
inputy.value = "y_" + i;
inputx.addEventListener("focus",function(){if(this.value==this.id) this.value="";});
inputy.addEventListener("focus",function(){if(this.value==this.id) this.value="";});
document.getElementById("pointsdiv").appendChild(inputx);
document.getElementById("pointsdiv").appendChild(inputy);
document.getElementById("pointsdiv").appendChild(br);
}
document.getElementById("pointsdiv").id="pointsdiv_after";
}
else
{
if( old_n < n )
{
for(i=old_n+1;i<=n;i++){
inputx = document.createElement('input');
inputy = document.createElement('input');
br = document.createElement('br');
inputx.type = "text";
inputy.type = "text";
inputx.size = 3;
inputy.size = 3;
inputx.id = "x_" + i;
inputy.id = "y_" + i;
inputx.value = "x_" + i;
inputy.value = "y_" + i;
inputx.addEventListener("focus",function(){if(this.value==this.id) this.value="";});
inputy.addEventListener("focus",function(){if(this.value==this.id) this.value="";});
document.getElementById("pointsdiv_after").appendChild(inputx);
document.getElementById("pointsdiv_after").appendChild(inputy);
document.getElementById("pointsdiv_after").appendChild(br);
}
}
else
{
var parent;
for(i=n+1;i<=old_n;i++){
parent = document.getElementById("pointsdiv_after");
parent.removeChild(parent.lastChild);
parent.removeChild(parent.lastChild);
parent.removeChild(parent.lastChild);
}
}
}
});
//BEZIER CURVE
function factorial(n){
var result=1;
for(i=2;i<=n;i++){
result = result*i;
}
return result;
}
function Point(x,y){
this.x=x;
this.y=y;
}
var points = new Array();
function getPoint(t){
var i;
var x=points[0].x;
var y=points[0].y;
var factn = factorial(n);
for(i=0;i<n;i++){
var b = factn / (factorial(i)*factorial(n-i));
var k = Math.pow(1-t,n-i)*Math.pow(t,i);
// console.debug( i+": ",points[i] );
x += b*k*points[i].x;
y += b*k*points[i].y;
}
return new Point(x, y);
}
//--BEZIER CURVE
submit.addEventListener("click",function(){
if(n){
for(i=1;i<=n;i++){
var px = document.getElementById("x_"+i);
var py = document.getElementById("y_"+i);
points.push(new Point(parseInt(px.value,10),parseInt(py.value,10)));
// console.debug( points[i-1] );
}
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
context.beginPath();
console.debug( points[0].x, points[0].y );
context.moveTo(points[0].x, points[0].y);
var t=0.01;
while (t<=1)
{
//get coordinates at position
var p=getPoint(t);
// console.debug( p.x, p.y );
//draw line to coordinates
context.lineTo(p.x, p.y);
//increment position
t += 0.01;
}
context.stroke();
}
});
}
</script>
window.onload=function(){
var old_n=0,n=0;
var nrSelect=document.getElementById(“mySelect”);
var submit=document.getElementById(“提交”);
nrSelect.addEventListener(“更改”,函数(){
旧n=n;
n=nrSelect.selectedIndex;
var输入x,输入,br;
if(document.getElementById(“pointsdiv”))
{
对于(i=1;i我不是画布或几何学方面的专家,但我的想法是:在绘制伪线之前,你不应该移动到点[0]
,因为你的getPoint
函数似乎将你引导到那里。在调试代码时,我可以看到你首先移动到(20,20)
,然后画一条直线(大致)到(40,40)
,然后开始逐渐回到(20,20)
,生成一个你不想要的闭合形状
对代码进行一个小的(快速且肮脏的)更改使其开始绘制曲线:
// DO NOT MOVE TO HERE
//context.moveTo(points[0].x, points[0].y);
var t = 0.01;
// MOVE TO THE FIRST POINT RETURNED BY getPoint
var p0 = getPoint(t);
context.moveTo(p0.x, p0.y);
t+=0.01;
// now loop from 0.02 to 1...
我相信你可以把它重构成更好的东西,就像我说的那样,我的更改又快又脏
我不是画布或几何学方面的专家,但我的想法是:在绘制伪线之前,你不应该移动到点[0]
,因为你的getPoint
函数似乎将你引导到这一点。在调试代码时,我看到的是,你首先移动到(20,20)
,然后画了一条直线(大致上)(40,40)
,然后开始逐渐拉回(20,20)
,生成一个你不想要的封闭形状
对代码进行一个小的(快速且肮脏的)更改使其开始绘制曲线:
// DO NOT MOVE TO HERE
//context.moveTo(points[0].x, points[0].y);
var t = 0.01;
// MOVE TO THE FIRST POINT RETURNED BY getPoint
var p0 = getPoint(t);
context.moveTo(p0.x, p0.y);
t+=0.01;
// now loop from 0.02 to 1...
我相信你可以把它重构成更好的东西,就像我说的那样,我的更改又快又脏
请提供一个例子,填补代码中缺失的空白,并对其进行格式化。这几乎是在画一些东西,但它不是它应该的样子。即使有3个点,它也画了一条曲线,但曲线看起来不像它应该的样子。您还想让我发布整个代码吗?不,请不要在这里发布整个代码。我相信Alexander是在要求r在JSFIDLE或类似平台上的实时演示。为什么不使用?我没有使用bezierCurveTo,因为我不限于3分。这是JSFIDLE链接:。如果我给2分,比如(20,20)和(100,20)它应该画一条直线,但它画了一些奇怪的东西。请提供一个例子,填补代码中缺失的空白并格式化它。它几乎画了一些东西,但它不是它应该的样子。即使有3个点,它也画了一条曲线,但曲线看起来不像它应该的样子。你想让我发布整个代码吗?不,请不要发布全部代码都在这里。我相信Alexander要求在JSFIDLE或类似平台上进行现场演示。为什么不使用?我没有使用bezierCurveTo,因为我不限于3分。这里是JSFIDLE链接:。如果我给2分,比如(20,20)和(100,20)它应该画一条直线,但它画了一些奇怪的东西谢谢你花时间!现在它实际上画了一些更接近我想要的东西,但它仍然不是贝塞尔曲线。我真的不知道为什么…也许数学是错的,但我反复检查,它似乎不是。哦,我发现了一个已经实现的函数在jsdraw2D中,我将使用它,因为它工作正常。非常感谢你花时间!现在它实际上画出了更接近我想要的东西,但它仍然不是贝塞尔曲线。我真的不知道为什么。也许数学是错的,但我一遍又一遍地检查它,它似乎不是。哦,我发现了一条已经很小的曲线在jsdraw2D中实现了这个函数,现在我将使用它,因为它工作正常