2015-06-11 83 views
0

不知道还有什么地方可以问这个。我在HTML中使用了一个,并希望绘制从画布左下角开始的弹丸轨迹,以一定的速度(如45degrees,位于10ms)以一定角度拍摄。到目前为止,我已经看到使用在javascript中绘制轨迹?

ctx.beginPath(); 

ctx.moveTo(0, 0); 

ctx.lineTo((180), 180); 

ctx.stroke(); 

但是,只绘制一条直线?

+0

添加一个你想要的工作代码示例(在JSbin中为例子e)以及你期待的更详细的信息 – Sirikon

+0

这个问题过于宽泛,如果问题是......绘制一个轨迹,首先应该确定是否存在重力,如果计算抛射体的质量,是否存在空气阻力。你应该使用物理引擎来简化你的生活。 – SharpEdge

回答

2

你想要的是一个在X和Y方向都有速度的物体。对于每次迭代,您都会因重力而降低Y的速度。对于每次迭代,您可以绘制一条线,请参阅下面的示例。

var c = document.getElementById("canvas"); 
 
var ctx = c.getContext("2d"); 
 

 
c.width = 450; 
 
c.height = 300; 
 

 
var x = 0; 
 
var y = 300; 
 
var oldX = 0; 
 
var oldY = 300; 
 
var xVel = 10; 
 
var yVel = -20; 
 
var g = 1; 
 

 

 
var myInterval = setInterval(function() { 
 
           x+=xVel; 
 
           y+=yVel; 
 
           yVel+=g; 
 
           ctx.beginPath(); 
 
           ctx.moveTo(oldX,oldY); 
 
           ctx.lineTo(x,y); 
 
           ctx.stroke(); 
 
           oldX = x; 
 
           oldY = y; 
 
    
 
    if (y>c.height) {clearInterval(myInterval);} 
 
          },20);
canvas { 
 
    border: 1px solid black; 
 
}
<canvas id="canvas"></canvas>

3

有一些准确的[X,Y]轨迹计算在维基百科:

http://en.wikipedia.org/wiki/Trajectory_of_a_projectile

但如果你只是想你的抛射形成电弧到目标你可以这样做:

  • 鉴于起点(P0)和目标点(P2),
  • 在指定的距离(P1)计算垂直于P0 & p2的中点的点,
  • 从P0绘制二次曲线到P2与p1作为曲线中间控制点。

enter image description here

如果你想沿着二次曲线,你可以使用德卡斯特里奥算法,然后绘制你的弹丸沿着绘制的点积点:

function getQuadraticBezierXYatT(startPt,controlPt,endPt,T) { 
    var x = Math.pow(1-T,2) * startPt.x + 2 * (1-T) * T * controlPt.x + Math.pow(T,2) * endPt.x; 
    var y = Math.pow(1-T,2) * startPt.y + 2 * (1-T) * T * controlPt.y + Math.pow(T,2) * endPt.y; 
    return({x:x,y:y}); 
} 

var canvas=document.getElementById("canvas"); 
 
var ctx=canvas.getContext("2d"); 
 
var cw=canvas.width; 
 
var ch=canvas.height; 
 

 
var p0={x:0,y:ch}; 
 
var p2={x:180,y:180}; 
 
var distance=25; 
 
var p1; 
 

 
var nextTime=0; 
 
var delay=1000/60*3; 
 
var pts; 
 
var ptIndex=0; 
 

 
redraw(); 
 

 
$myslider=$('#myslider'); 
 
$myslider.attr({min:0,max:100}).val(distance); 
 
$myslider.on('input change',function(){ 
 
    distance=parseInt($(this).val()); 
 
    redraw(); 
 
}); 
 

 
$('#plot').click(function(){ 
 
    pts=plot(p0,p1,p2); 
 
    ptIndex=0; 
 
    requestAnimationFrame(animatePlot);  
 
}); 
 

 
function animatePlot(time){ 
 
    // if(time<nextTime){requestAnimationFrame(animatePlot);} 
 
    nextTime=time+delay; 
 
    if(ptIndex<pts.length){ 
 
    var p=pts[ptIndex]; 
 
    ctx.clearRect(0,0,cw,ch); 
 
    ctx.beginPath(); 
 
    ctx.arc(p.x,p.y,2,0,Math.PI*2); 
 
    ctx.closePath(); 
 
    ctx.fill(); 
 
    ctx.beginPath(); 
 
    ctx.arc(p2.x,p2.y,4,0,Math.PI*2); 
 
    ctx.closePath(); 
 
    ctx.fill(); 
 
    ctx.fillText('['+p2.x+','+p2.y+']',p2.x+10,p2.y);   
 
    ptIndex++; 
 
    requestAnimationFrame(animatePlot); 
 
    } 
 
} 
 

 
function plot(p0,p1,p2){ 
 
    var pts=[]; 
 
    var lastX=p0.x; 
 
    var lastY=p0.y; 
 
    for(var T=0;T<500;T++){ 
 
    var p=getQuadraticBezierXYatT(p0,p1,p2,T/500); 
 
    var dx=p.x-lastX; 
 
    var dy=p.y-lastY; 
 
    if(dx*dx+dy*dy>1){ 
 
     pts.push({x:p.x,y:p.y}); 
 
     lastX=p.x; 
 
     lastY=p.y; 
 
    } 
 
    } 
 
    return(pts) 
 
} 
 

 
function redraw(){ 
 
    p1=pointPerpendicularToMidpoint(p0,p2,distance); 
 
    ctx.clearRect(0,0,cw,ch); 
 
    ctx.beginPath(); 
 
    ctx.moveTo(p0.x,p0.y); 
 
    ctx.quadraticCurveTo(p1.x,p1.y,p2.x,p2.y); 
 
    ctx.stroke(); 
 
    ctx.beginPath(); 
 
    ctx.arc(p2.x,p2.y,4,0,Math.PI*2); 
 
    ctx.closePath(); 
 
    ctx.fill(); 
 
    ctx.fillText('['+p2.x+','+p2.y+']',p2.x+10,p2.y); 
 
} 
 

 

 
function pointPerpendicularToMidpoint(p0,p2,distance){ 
 
    var dx=p2.x-p0.x; 
 
    var dy=p2.y-p0.y; 
 
    var midpoint={ x:p0.x+dx*0.50, y:p0.y+dy*0.50, }; 
 
    var angle=Math.atan2(dy,dx); 
 
    var perpendicularPoint={ 
 
    x: midpoint.x+distance*Math.cos(angle-Math.PI/2), 
 
    y: midpoint.y+distance*Math.sin(angle-Math.PI/2)   
 
    }; 
 
    return(perpendicularPoint); 
 
} 
 

 
function getQuadraticBezierXYatT(startPt,controlPt,endPt,T) { 
 
    var x = Math.pow(1-T,2) * startPt.x + 2 * (1-T) * T * controlPt.x + Math.pow(T,2) * endPt.x; 
 
    var y = Math.pow(1-T,2) * startPt.y + 2 * (1-T) * T * controlPt.y + Math.pow(T,2) * endPt.y; 
 
    return({x:x,y:y}); 
 
}
body{ background-color: ivory; } 
 
#canvas{border:1px solid red; margin:0 auto; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> 
 
Change Curve:&nbsp<input id=myslider type=range> 
 
<br> 
 
<button id=plot>Plot the curve</button> 
 
<br> 
 
<canvas id="canvas" width=300 height=250></canvas>