使用数学来改变对象的位置(javascript)

时间:2016-05-15 21:25:57

标签: javascript animation svg

我有一个很大的要求。它涉及相当多的数学,这从来都不是我的强项,所以我想,我会问Stackoverflow上的人帮助我。

我正在使用Javascript处理这个太阳系交互式动画。我正在使用三角函数在物体周围创建完整的360度旋转旋转,用于围绕太阳的行星。我知道,行星会以椭圆形旋转,但我不想让它对我自己造成太大的压力。

function rotate_point(originX, originY, body) {
    body.angle +=  (1.0 / body.period); //calculates the angle, divided by distance from center of body
    var ang = body.angle * 2.0 * Math.PI / 180.0; //calculates full 360° rotation required based on angle
    var r = body.orbit;
    return {
        x: Math.cos(ang) * r - Math.sin(ang) * r + originX, 
        y: Math.sin(ang) * r + Math.cos(ang) * r + originY 
    };} // generic rendering of a unit orbital progression of a planet

正如你所看到的那部分已经完成,我的问题是:

我需要“调整”以便将物体驱动到太阳中心的效果。就像我突然使引力拉得更强,它会拉动行星的轨道,所以你看到它们最终撞向那个中心。

是否可以对上述代码进行任何更改,如果是,那么代码需要看起来像什么?

我有一个JS小提琴我已经得到了什么,我希望有一些聪明的家伙能看到这个挑战并帮助我!

FIDDLE

3 个答案:

答案 0 :(得分:5)

更新代码以使用开普勒的行星运动第三定律应该非常容易。因为你在使用圆形轨道,其中质量(行星)<<质量(太阳),开普勒第三定律基本上只是角动量守恒的一个陈述。

旋转动量定义为系统惯性矩( I )和角速度(ω)的乘积,以 rad为单位测量/ s的

数学上,这只是:

  

I1 * omega1 = I2 * omega2

根据我们可以使用的数量来表达:

  

I = m * r ^ 2   omega = r * dTheta / dt

所以通过财产保护:

  

I1 * omega1 = I2 * omega2

群众取消了双方,留下了 r omega 的表达。

  

r1 ^ 2 * omega1 = r2 ^ 2 * omega2

因此,考虑到半径的变化,我们可以计算角速度的必要变化。如果 r1 omega1 是初始半径和旋转速度,则给定轨道半径的新旋转速度表示为:

  

omega2 = omega1 *(r1 / r2)^ 2

这可以通过在function rotate_point(originX, originY, body) { velocity_gain = Math.pow(sol["Earth"].orbit/body.orbit, 2) body.angle += velocity_gain * (1.0 / body.period); //calculates the angle, divided by distance from center of body var ang = body.angle * 2.0 * Math.PI / 180.0; //calculates full 360° rotation required based on angle var r = body.orbit * orbitScale return { x: Math.cos(ang) * r - Math.sin(ang) * r + originX, y: Math.sin(ang) * r + Math.cos(ang) * r + originY }; } // generic rendering of a unit orbital progression of a planet function planetrotation ( planet ) { var x, y, x_sun, y_sun, e, c_new; e = document.getElementById ( planet ); x_sun = parseFloat ( document.getElementById ( "Sun" ).getAttribute ( "cx" ) ); y_sun = parseFloat ( document.getElementById ( "Sun" ).getAttribute ( "cy" ) ); c_new = rotate_point ( x_sun, y_sun, sol[planet], 0.5 ); e.setAttribute ( "cx", c_new.x ); e.setAttribute ( "cy", c_new.y ); } // Rotations of the planets around Sun var sol = { Mars: { period: 5.2, orbit: 400, angle: 51.0}, Earth: { period: 5.2, orbit: 300, angle: 51.0}, Venus: { period: 5.2, orbit: 200, angle: 51.0} }; function animate () { planetrotation("Venus"); planetrotation("Earth"); planetrotation("Mars"); } 函数中添加一行代码来更新速度来实现:

period

这里是小提琴模拟3个行星:https://jsfiddle.net/8kcj3bvz/

enter image description here

基本上,这种平等性表明,随着轨道半径的减小,动量(和这种情况下的能量)的角速度必须增加。

长期来看,您可能需要考虑使用Euler的方法来模拟此系统。对于像这样的引力体,它实际上非常简单,并且在模拟两个以上的物体时可以非常强大。

修改

只是注意到轨道速度只是其半径的函数,前提是卫星的质量远小于母体。因此,在代码中定义anglefor(var i = 0; i<content.length(); i++){ //perform whatever you need on the following object var myobject = content[i]; } 实际上是多余的。

答案 1 :(得分:3)

你可以减少轨道的半径:

body.orbit = Math.max(body.orbit-.25, 0);

function rotate_point(originX, originY, body) {
  body.angle += (1.0 / body.period); //calculates the angle, divided by distance from center of body
  var ang = body.angle * 2.0 * Math.PI / 180.0; //calculates full 360° rotation required based on angle
  body.orbit = Math.max(body.orbit - .25, 0);
  var r = body.orbit;
  return {
    x: Math.cos(ang) * r - Math.sin(ang) * r + originX,
    y: Math.sin(ang) * r + Math.cos(ang) * r + originY
  };
}
// generic rendering of a unit orbital progression of a planet

function planetrotation(planet) {
  var x, y, x_sun, y_sun, e, c_new;
  e = document.getElementById(planet);
  x_sun = parseFloat(document.getElementById("Sun").getAttribute("cx"));
  y_sun = parseFloat(document.getElementById("Sun").getAttribute("cy"));
  c_new = rotate_point(x_sun, y_sun, sol[planet]);
  e.setAttribute("cx", c_new.x);
  e.setAttribute("cy", c_new.y);
} // Rotations of the planets around Sun    

var sol = {
  Earth: {
    period: 5.2,
    orbit: 200,
    angle: 51.0
  }
};

function animate() {
  planetrotation("Earth");
}

var animateInterval = setInterval(animate, 1000 / 60);
.st0 {
  fill: #FFFF00;
}
.st1 {
  fill: blue;
}
<div class="solarsystem">
  <svg xmlns="http://www.w3.org/2000/svg" id="solly" viewBox="0 0 1000 600">
    <g id="Sun2">
      <circle id="Sun" class="st0" cx="500" cy="300.8" r="30" />
      <circle id="Earth" class="st1" cx="375.4" cy="289.7" r="10.5" />
    </g>
  </svg>
</div>

当然,在物理上它不会像这样。

答案 2 :(得分:2)

为简单起见,您可以在时间内线性改变半径。例如:

function rotate_point(originX, originY, body) {
    body.angle +=  (1.0 / body.period); //calculates the angle, divided by distance from center of body
    body.orbit -= body.period*.04;
    // ... other stuff ...
}