T
T
getElementById("canvas");
const ctx = canvas.getContext("2d");
canvas.width = 800;
canvas.height = 600;
class Point {
constructor(x, y, pinned = false) {
this.x = x;
this.y = y;
this.oldX = x;
this.oldY = y;
this.pinned = pinned;
}
update() {
if (this.pinned) return;
let vx = (this.x - this.oldX) * FRICTION;
let vy = (this.y - this.oldY) * FRICTION + GRAVITY;
this.oldX = this.x;
this.oldY = this.y;
this.x += vx;
this.y += vy;
}
}
function constrainPoints() {
for (let i = 0; i < points.length - 1; i++) {
let p1 = points[i];
let p2 = points[i + 1];
let dx = p2.x - p1.x;
let dy = p2.y - p1.y;
let distance = Math.sqrt(dx * dx + dy * dy);
let difference = SPACING - distance;
let percent = difference / distance / 2;
let offsetX = dx * percent;
let offsetY = dy * percent;
if (!p1.pinned) {
p1.x -= offsetX;
p1.y -= offsetY;
}
if (!p2.pinned) {
p2.x += offsetX;
p2.y += offsetY;
}
}
}
function update() {
for (let p of points) p.update();
for (let i = 0; i < 5; i++) constrainPoints();
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.moveTo(points[0].x, points[0].y);
for (let p of points) {
ctx.lineTo(p.x, p.y);
}
ctx.stroke();
}
function animate() {
update();
draw();
requestAnimationFrame(animate);
}
animate();