Skip to content

Instantly share code, notes, and snippets.

@duyixian1234
Last active December 20, 2023 09:04
Show Gist options
  • Select an option

  • Save duyixian1234/2a380814edc8542d280950a9225c510f to your computer and use it in GitHub Desktop.

Select an option

Save duyixian1234/2a380814edc8542d280950a9225c510f to your computer and use it in GitHub Desktop.
Double Pendulum Animation
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Double Pendulum Animation</title>
</head>
<body>
<canvas id="canvas" width="800" height="600"></canvas>
<script src="script.js"></script>
</body>
</html>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const width = canvas.width;
const height = canvas.height;
const pivot1 = { x: width / 2, y: height / 2 };
const pivot2 = { x: width / 2, y: height / 2 + 100 };
const arm1Length = 100;
const arm2Length = 80;
const arm1Mass = 10;
const arm2Mass = 10;
const gravity = 1;
const showTrace = true;
const damping = 1;
let angle1 = Math.PI / 2;
let angle2 = Math.PI / 2;
let angle1Velocity = 0;
let angle2Velocity = 0;
const tracePoints = []; // Array to store trace points
function draw() {
ctx.clearRect(0, 0, width, height);
const arm1X = pivot1.x + Math.sin(angle1) * arm1Length;
const arm1Y = pivot1.y + Math.cos(angle1) * arm1Length;
const arm2X = arm1X + Math.sin(angle2) * arm2Length;
const arm2Y = arm1Y + Math.cos(angle2) * arm2Length;
ctx.beginPath();
ctx.moveTo(pivot1.x, pivot1.y);
ctx.lineTo(arm1X, arm1Y);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(arm1X, arm1Y);
ctx.lineTo(arm2X, arm2Y);
ctx.stroke();
ctx.beginPath();
ctx.arc(arm1X, arm1Y, arm1Mass, 0, Math.PI * 2);
ctx.fillStyle = "red";
ctx.fill();
ctx.beginPath();
ctx.arc(arm2X, arm2Y, arm2Mass, 0, Math.PI * 2);
ctx.fillStyle = "blue";
ctx.fill();
if (showTrace) {
tracePoints.push({ x: arm2X, y: arm2Y }); // Add current point to tracePoints array
if (tracePoints.length > 300) {
tracePoints.shift(); // Remove first element from array
}
ctx.beginPath();
ctx.moveTo(tracePoints[0].x, tracePoints[0].y);
for (let i = 1; i < tracePoints.length; i++) {
ctx.lineTo(tracePoints[i].x, tracePoints[i].y);
}
ctx.strokeStyle = "gray";
ctx.stroke();
}
const num1 = -gravity * (2 * arm1Mass + arm2Mass) * Math.sin(angle1);
const num2 = -arm2Mass * gravity * Math.sin(angle1 - 2 * angle2);
const num3 = -2 * Math.sin(angle1 - angle2) * arm2Mass;
const num4 =
angle2Velocity * angle2Velocity * arm2Length +
angle1Velocity * angle1Velocity * arm1Length * Math.cos(angle1 - angle2);
const den =
arm1Length *
(2 * arm1Mass + arm2Mass - arm2Mass * Math.cos(2 * angle1 - 2 * angle2));
const angle1Acceleration = (num1 + num2 + num3 * num4) / den;
const num5 = 2 * Math.sin(angle1 - angle2);
const num6 =
angle1Velocity * angle1Velocity * arm1Length * (arm1Mass + arm2Mass);
const num7 = gravity * (arm1Mass + arm2Mass) * Math.cos(angle1);
const num8 =
angle2Velocity *
angle2Velocity *
arm2Length *
arm2Mass *
Math.cos(angle1 - angle2);
const den2 =
arm2Length *
(2 * arm1Mass + arm2Mass - arm2Mass * Math.cos(2 * angle1 - 2 * angle2));
const angle2Acceleration = (num5 * (num6 + num7 + num8)) / den2;
angle1Velocity = damping * (angle1Velocity + angle1Acceleration);
angle2Velocity = damping * (angle2Velocity + angle2Acceleration);
angle1 += angle1Velocity;
angle2 += angle2Velocity;
requestAnimationFrame(draw);
}
draw();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment