2015-06-11 124 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>