<html>
<head>
<meta charset=utf-8 />
<title>JS Bin</title>
</head>
<body>
</body>
</html>
function BallObject(elasticity) {
this.v = { x: 1, y: 20 }; // velocity: m/s^2
this.m = 10; // mass: kg
this.p = { x: 40, y: 0}; // position
this.r = 15; // radius of obj
this.cr = elasticity; // elasticity
}
function draw(obj) {
ctx.beginPath();
ctx.arc(obj.p.x, obj.p.y, obj.r, 0, 2 * Math.PI);
ctx.closePath();
ctx.stroke();
ctx.fill();
}
function collide(obj) {
obj.v.y = (obj.cr * floor.m * -obj.v.y + obj.m * obj.v.y) / (obj.m + floor.m);
}
function update(obj, dt) {
// over-simplified collision detection
// only consider the floor for simplicity
if ((obj.p.y + obj.r) > c.height) {
obj.p.y = c.height - obj.r;
collide(obj);
}
obj.v.y += g * dt;
obj.p.x += obj.v.x * dt * ppm;
obj.p.y += obj.v.y * dt * ppm;
}
var d = document,
c = d.createElement('canvas'),
b = d.createElement('button'),
els = d.createElement('input'),
clr = d.createElement('input'),
clrl = d.createElement('label'),
ctx = c.getContext('2d'),
fps = 60, // target frames per second
ppm = 20, // pixels per meter
g = 9.8, // m/s^2 - acceleration due to gravity
objs = [],
floor = {
v: { x: 0, y: 0 }, // floor is immobile
m: 5.9722 * Math.pow(10, 24) // mass of earth (probably could be smaller)
},
t = new Date().getTime();
b.innerHTML = 'add ball with elasticity: <span>0.70</span>';
b.onclick = function() { objs.push(new BallObject(els.value / 100)); };
els.type = 'range';
els.min = 0;
els.max = 100;
els.step = 1;
els.value = 70;
els.style.display = 'block';
els.onchange = function() {
b.getElementsByTagName('span')[0].innerHTML = (this.value / 100).toFixed(2);
};
clr.type = 'checkbox';
clr.checked = true;
clrl.appendChild(clr);
clrl.appendChild(d.createTextNode('clear each frame'));
c.style.border = 'solid 1px #3369ff';
c.style.borderRadius = '10px';
c.style.display = 'block';
c.width = 400;
c.height = 400;
ctx.fillStyle = 'rgb(100,200,255)';
ctx.strokeStyle = 'rgb(33,69,233)';
d.body.appendChild(c);
d.body.appendChild(els);
d.body.appendChild(b);
d.body.appendChild(clrl);
setInterval(function() {
var nt = new Date().getTime(),
dt = (nt - t) / 1000;
if (clr.checked) {
ctx.clearRect(0, 0, c.width, c.height);
}
for (var i = 0; i < objs.length; i++) {
update(objs[i], dt);
draw(objs[i]);
}
t = nt;
}, 1000 / fps);
Output
You can jump to the latest bin by adding /latest
to your URL
Keyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |