JSFiddle - React, Tailwind, and code Playground
HTML
<canvas id="physics" width="500px" height="500px"></canvas>
CSS
canvas#physics {
border: 1px solid #000000;
}
JavaScript
var canvas = $('#physics')[0];
var ctx = canvas.getContext('2d');
var canvas_rect = canvas.getBoundingClientRect();
var mouse = {x: 0, y: 0};
canvas.addEventListener('mousemove', function(e){
mouse = {x: e.clientX - canvas_rect.left, y: e.clientY - canvas_rect.top};
});
function SpringMass(){
var self = this;
self.angle = 0;
self.bar_len = 125;
self.mass = 20;
self.m_position = null;
self.last_time = null;
self.mass_from_angle = function(){
self.m_position = {
x: mouse.x + Math.cos(self.angle)*self.bar_len,
y: mouse.y + Math.sin(self.angle)*self.bar_len
};
};
self.mass_from_angle();
self.run = function(){
// Perform actions for a frame
self.compute();
self.draw();
};
self.compute = function(){
// Gather dt
var dt = 0;
if (self.last_time !== null){
var now = new Date().getTime();
dt = now - self.last_time;
self.last_time = now;
}
self.angle = Math.atan2(self.m_position.y - mouse.y, self.m_position.x - mouse.x);
self.mass_from_angle();
};
self.draw = function(){
// Draw the bar
ctx.beginPath();
ctx.moveTo(mouse.x, mouse.y);
ctx.lineTo(self.m_position.x, self.m_position.y);
ctx.stroke();
// Draw $m$
ctx.fillStyle = '#DDDDDD';
ctx.beginPath();
ctx.arc(self.m_position.x, self.m_position.y, 20, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();
// Draw $p$
ctx.fillStyle = '#FF0000';
ctx.beginPath();
ctx.arc(mouse.x, mouse.y, 5, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();
};
}
var spring_mass = new SpringMass();
setInterval(function(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
spring_mass.run();
}, 1000/15);