Earlier we worked on making all the dots draggable, but what’s better than simply dragging dots? Let’s set up a way to throw the dots! Now as we drag it we record the positions and use that to calculate a new velocity. Then when a dot is dropped, it will have a trajectory to follow that matches the path and speed it was dragged. This iteration only looks at the current frame and the previous frame, but a better solution may be to average the previous few positions to get a better feel. I’ve noticed that (with a mouse especially) people tend to stop dragging just before they mouseup, so this kills any velocity the dot receives during the drag. Enjoy throwing the dots around the canvas! interactive physics animations via javascript & canvas | 15.

[cc lang=”javascript”]

$(function () {

var canvas, context, width, height, x, y, radius = 25, clickX, clickY, drag = false;

var total_dots = 10;

var fps = 24;

canvas = $(“#canvas”)[0];

context = canvas.getContext(“2d”);

var dots = new Array();

var drag_i = -1;

var gravity = 2;

var friction = .98;

var bounce = -.96;

var this_dot = {};

for (var i=0; i < total_dots; i++){
createDot();
}
function createDot(x, y, r, vx, vy){
var this_dot = {
x: typeof(x) != 'undefined' ? x : Math.random()*canvas.width,
y: typeof(y) != 'undefined' ? y : Math.random()*canvas.height,
radius: typeof(r) != 'undefined' ? r : Math.random()*20+10,
vx: typeof(vx) != 'undefined' ? vx : Math.random()*30-10,
vy: typeof(vy) != 'undefined' ? vy : Math.random()*30-10
};
dots.push(this_dot);
}
draw();
$("#canvas").mousedown(function (event) {
var dx, dy, dist;
for (var i=0; i < dots.length; i++){
dx = event.pageX - this.offsetLeft - dots[i].x;
dy = event.pageY - this.offsetTop - dots[i].y;
dist = Math.sqrt(dx * dx + dy * dy);
if(dist < radius) {
drag = true;
drag_i = i
clickX = dx;
clickY = dy;
continue;
}
}
//none clicked
if (!drag) {
createDot(event.pageX - this.offsetLeft, event.pageY - this.offsetTop);
}
});
$("#canvas").mouseup(function (event) {
drag = false;
drag_i = -1;
});
$("#canvas").mousemove(function (event) {
if(drag) {
dots[drag_i].old_x = dots[drag_i].x;
dots[drag_i].old_y = dots[drag_i].y;
dots[drag_i].x = event.pageX - this.offsetLeft - clickX;
dots[drag_i].y = event.pageY - this.offsetTop - clickY;
dots[drag_i].vx = dots[drag_i].x - dots[drag_i].old_x;
dots[drag_i].vy = dots[drag_i].y - dots[drag_i].old_y;
draw();
}
});
function update(){
for (var i=0; i < dots.length; i++){
if (drag_i != i){
var this_dot = dots[i];
this_dot.vx *= friction;
this_dot.vy = this_dot.vy * friction + gravity;
this_dot.x += this_dot.vx;
this_dot.y += this_dot.vy;
if (this_dot.x > canvas.width – this_dot.radius){

this_dot.x = canvas.width – this_dot.radius;

this_dot.vx = this_dot.vx * bounce;

}

else if(this_dot.x < 0 + this_dot.radius){
this_dot.x = this_dot.radius;
this_dot.vx = this_dot.vx * bounce;
}
if (this_dot.y > canvas.height – this_dot.radius){

this_dot.y = canvas.height – this_dot.radius;

this_dot.vy = this_dot.vy * bounce;

}

else if(this_dot.y < 0 + this_dot.radius){
this_dot.y = this_dot.radius;
this_dot.vy = this_dot.vy * bounce;
}
}
}
}
function draw() {
context.clearRect(0, 0, canvas.width, canvas.height);
for (var i=0; i < dots.length; i++){
context.beginPath();
context.arc(dots[i].x, dots[i].y, dots[i].radius, 0, Math.PI * 2, false);
context.fill();
context.closePath();
}
}
setInterval(function() {
update();
draw();
}, 1000/fps);$("#gravity").click(function(){
if($("#gravity").is(':checked')){
gravity = 2;
}
else{
gravity = 0;
}
});
});
[/cc]Follow the whole Interactive Physics Animations via Javascript & Canvas series.