模拟轨道上物体的引力

aki*_*uri 5 javascript animation easing-functions easing html5-canvas

我试图在下面的动画中模拟引力/加速度.earth随着距离越来越近,角速度应该sol越来越大.我想我需要一个缓动功能来修改earth.angularVelocity但不知道怎么做.

我不知道是否已经定义了缓动函数定义函数.我需要的缓动函数应该像在这个图中一样工作:

拉/重新缓和功能图

earth的近日点是180°,远日点是0/360°.如何创建这样的功能并使其工作?

function pullRelease(angularPosition, begin, change, maxVelocity) {
    // ?
}
earth.angularVelocity = pullRelease(earth.angularPosition, 0, 360, 3);
Run Code Online (Sandbox Code Playgroud)

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

var sol = {
  x: 125,
  y: 150,
  r: 30,
  fill: "gold",
};

var orbit = {
  x: 200,
  y: 150,
  semiMajor: 150,
  semiMinor: 75,
};

var earth = {
  r: 15,
  fill: "dodgerblue",
  angularPosition: 0,
  angularVelocity: 1,
};

// draw sun
context.beginPath();
context.arc(sol.x, sol.y, sol.r, 0, 360 * Math.PI / 180);
context.fillStyle = sol.fill;
context.fill();
// draw fake sun to mark the orbit center
context.beginPath();
context.arc(orbit.x, orbit.y, sol.r, 0, 360 * Math.PI / 180);
context.fillStyle = "rgba(255,215,0,.1)";
context.fill();
// draw earth's orbit path
context.beginPath();
context.ellipse(orbit.x, orbit.y, orbit.semiMajor, orbit.semiMinor, 0, 0, 2 * Math.PI);
context.stroke();
// these are fixed, so save them as background-image
canvas.style.backgroundImage = "url(" + canvas.toDataURL() + ")";

function draw() {
  context.resetTransform();
  context.clearRect(0, 0, canvas.width, canvas.height);

  var newPosition = rotate(-earth.angularPosition, orbit.semiMajor, orbit.semiMinor, orbit.x, orbit.y);

  earth.x = newPosition.x;
  earth.y = newPosition.y;
  // earth.angularVelocity = pullRelease(earth.angularPosition, 0, 360, 3);
  earth.angularPosition += earth.angularVelocity;

  if (earth.angularPosition >= 360) {
    earth.angularPosition = 0;
  }
  position.innerHTML = earth.angularPosition + "°";

  context.translate(earth.x, earth.y);

  context.beginPath();
  context.arc(0, 0, earth.r, 0, 360 * Math.PI / 180);
  context.closePath();
  context.fillStyle = earth.fill;
  context.fill();

  requestAnimationFrame(draw);
}

requestAnimationFrame(draw);

function rotate(angle, distanceX, distanceY, originX, originY) {
  return {
    x: originX + Math.cos(angle * Math.PI / 180) * distanceX,
    y: originY + Math.sin(angle * Math.PI / 180) * distanceY,
  }
}
Run Code Online (Sandbox Code Playgroud)
body {
  background: gainsboro;
}
canvas {
  background: white;
  box-shadow: 1px 1px 1px rgba(0, 0, 0, .1);
}
#position {
  display: inline-block;
  width: 35px;
  text-align: right;
}
Run Code Online (Sandbox Code Playgroud)
<canvas id="canvas" class="box" width="400" height="300"></canvas>
<p>Position: <span id="position">0</span></p>
Run Code Online (Sandbox Code Playgroud)

aki*_*uri 2

经过一番思考,我想出了一个似乎可以工作的函数,但我仍然认为效果感觉不自然。函数生成左侧的图表。理想的应该是右边的那个。所以这个功能还需要一些工作。

\n\n

在此输入图像描述

\n\n
function pullRelease(angularPosition, begin, change, minVelocity, maxVelocity) {\n    var midWay = Math.floor(change/2);\n    if (angularPosition >= begin && angularPosition < midWay) {\n        var percent = angularPosition / midWay;\n        return minVelocity + (maxVelocity-minVelocity) * percent;\n    }\n    else if (angularPosition == midWay) {\n        return maxVelocity;\n    }\n    else if (angularPosition > midWay && angularPosition <= change) {\n        var midWayOffset = angularPosition - midWay;\n        var remaining    = midWay - midWayOffset;\n        var percent      = remaining / midWay;\n        return minVelocity + (maxVelocity-minVelocity) * percent;\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

\r\n
\r\n
function pullRelease(angularPosition, begin, change, minVelocity, maxVelocity) {\n    var midWay = Math.floor(change/2);\n    if (angularPosition >= begin && angularPosition < midWay) {\n        var percent = angularPosition / midWay;\n        return minVelocity + (maxVelocity-minVelocity) * percent;\n    }\n    else if (angularPosition == midWay) {\n        return maxVelocity;\n    }\n    else if (angularPosition > midWay && angularPosition <= change) {\n        var midWayOffset = angularPosition - midWay;\n        var remaining    = midWay - midWayOffset;\n        var percent      = remaining / midWay;\n        return minVelocity + (maxVelocity-minVelocity) * percent;\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\r\n
var canvas = document.getElementById("canvas");\r\nvar context = canvas.getContext("2d");\r\n\r\nvar sol = {\r\n  x: 125,\r\n  y: 150,\r\n  r: 30,\r\n  fill: "gold",\r\n};\r\n\r\nvar orbit = {\r\n  x: 200,\r\n  y: 150,\r\n  semiMajor: 150,\r\n  semiMinor: 75,\r\n};\r\n\r\nvar earth = {\r\n  x: 0,\r\n  y: 0,\r\n  r: 15,\r\n  fill: "dodgerblue",\r\n  angularPosition: 0,\r\n  angularVelocity: 0,\r\n};\r\n\r\n// draw sun\r\ncontext.beginPath();\r\ncontext.arc(sol.x, sol.y, sol.r, 0, 360 * Math.PI / 180);\r\ncontext.fillStyle = sol.fill;\r\ncontext.fill();\r\n// draw fake sun to mark the orbit center\r\ncontext.beginPath();\r\ncontext.arc(orbit.x, orbit.y, sol.r, 0, 360 * Math.PI / 180);\r\ncontext.fillStyle = "rgba(255,215,0,.1)";\r\ncontext.fill();\r\n// draw earth\'s orbit path\r\ncontext.beginPath();\r\ncontext.ellipse(orbit.x, orbit.y, orbit.semiMajor, orbit.semiMinor, 0, 0, 2 * Math.PI);\r\ncontext.stroke();\r\n// these are fixed, so save them as background-image\r\ncanvas.style.backgroundImage = "url(" + canvas.toDataURL() + ")";\r\n\r\nfunction draw() {\r\n  context.resetTransform();\r\n  context.clearRect(0, 0, canvas.width, canvas.height);\r\n\r\n  var newPosition = rotate(-earth.angularPosition, orbit.semiMajor, orbit.semiMinor, orbit.x, orbit.y);\r\n  earth.x = newPosition.x;\r\n  earth.y = newPosition.y;\r\n\r\n  earth.angularVelocity = pullRelease(earth.angularPosition, 0, 360, 0.5, 5);\r\n  earth.angularPosition += earth.angularVelocity;\r\n\r\n  if (earth.angularPosition >= 360) {\r\n    earth.angularPosition = 0;\r\n  }\r\n  position.innerHTML = Math.floor(earth.angularPosition) + "\xc2\xb0";\r\n  velocity.innerHTML = (earth.angularVelocity).toFixed(2) + "\xc2\xb0";\r\n\r\n  context.translate(earth.x, earth.y);\r\n\r\n  context.beginPath();\r\n  context.arc(0, 0, earth.r, 0, 360 * Math.PI / 180);\r\n  context.closePath();\r\n  context.fillStyle = earth.fill;\r\n  context.fill();\r\n\r\n  requestAnimationFrame(draw);\r\n}\r\n\r\nrequestAnimationFrame(draw);\r\n\r\nfunction rotate(angle, distanceX, distanceY, originX, originY) {\r\n  return {\r\n    x: originX + Math.cos(angle * Math.PI / 180) * distanceX,\r\n    y: originY + Math.sin(angle * Math.PI / 180) * distanceY,\r\n  }\r\n}\r\n\r\nfunction pullRelease(angularPosition, begin, change, minVelocity, maxVelocity) {\r\n  var midWay = Math.floor(change / 2);\r\n  if (angularPosition >= begin && angularPosition < midWay) {\r\n    var percent = angularPosition / midWay;\r\n    return minVelocity + (maxVelocity - minVelocity) * percent;\r\n  } else if (angularPosition == midWay) {\r\n    return maxVelocity;\r\n  } else if (angularPosition > midWay && angularPosition <= change) {\r\n    var midWayOffset = angularPosition - midWay;\r\n    var remaining = midWay - midWayOffset;\r\n    var percent = remaining / midWay;\r\n    return minVelocity + (maxVelocity - minVelocity) * percent;\r\n  }\r\n}
Run Code Online (Sandbox Code Playgroud)\r\n
body {\r\n  background: gainsboro;\r\n}\r\ncanvas {\r\n  background: white;\r\n  box-shadow: 1px 1px 1px rgba(0, 0, 0, .1);\r\n}\r\n#position {\r\n  display: inline-block;\r\n  width: 35px;\r\n  text-align: right;\r\n}\r\n#velocity {\r\n  display: inline-block;\r\n  width: 35px;\r\n  text-align: right;\r\n}
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n