I’m really enjoying giving a control panel of sorts to the end user and letting them control the physics rules of their canvas. Let’s add more motion to it by applying a jitter to the velocity of each dot. This is similar to earlier, when we first started animating by applying a random number to the coordinates, but now we’ll apply a (smaller) random number to the velocity. This will be much smoother and will give a sense of real life to the dots. Straight lines and trajectories is always theoretical and hypothetical, but to make things look more real, sometimes we have to break the clean, straight lines. This will be another checkbox to control the float. I’m really enjoying the fact that the more properties we add to our controls we get exponentially more possible configurations. Perhaps we should even give a slider to control the strength of gravity…
interactive physics animations via javascript & canvas | 17.
[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 = 0;
var friction = .98;
var bounce = -.96;
var wrap = false;
var float = true;
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];
if (float){
this_dot.vx += Math.random() - .5;
this_dot.vy += Math.random() - .5;
}
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 (wrap){
if (this_dot.x > canvas.width + this_dot.radius){
this_dot.x -= canvas.width + this_dot.radius*2;
}
else if(this_dot.x < 0 - this_dot.radius){
this_dot.x += canvas.width + this_dot.radius*2;
}
if (this_dot.y > canvas.height + this_dot.radius){
this_dot.y -= canvas.height + this_dot.radius*2;
}
else if(this_dot.y < 0 - this_dot.radius){
this_dot.y += canvas.height + this_dot.radius*2;
}
}
else if (!wrap) {
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;
}
});
$("#wrap").click(function(){
if($("#wrap").is(':checked')){
wrap = true;
}
else{
wrap = false;
}
});
$("#float").click(function(){
if($("#float").is(':checked')){
float = true;
}
else{
float = false;
}
});
});
[/cc]Follow the whole Interactive Physics Animations via Javascript & Canvas series.