bouncing-dots/js/stuff.js
2016-04-02 19:28:27 -04:00

270 lines
9.8 KiB
JavaScript

var Stuff = function (options) {
options = options || {};
this.paused = false;
// Save this query here now that the page is loaded
this.canvas = document.getElementById("magic");
this.counter = 0;
};
/* Get the height and width of full document. To avoid browser
* incompatibility issues, choose the maximum of all height/width values.
*
* Method from http://stackoverflow.com/a/1147768 */
Stuff.prototype.getDocumentDimensions = function () {
var body = document.body,
html = document.documentElement;
var height = Math.max(body.scrollHeight, body.offsetHeight,
html.clientHeight, html.scrollHeight,
html.offsetHeight);
var width = Math.max(body.scrollWidth, body.offsetWidth,
html.clientWidth, html.scrollWidth,
html.offsetWidth);
return {"height": height, "width": width};
};
/* Choose a random RGB color */
Stuff.prototype.pickRandomColor = function() {
var normal = {"r": Math.floor(Math.random() * (255 + 1)),
"g": Math.floor(Math.random() * (255 + 1)),
"b": Math.floor(Math.random() * (255 + 1))};
var gamma = 2.2;
var L = 0.2126 * Math.pow(normal.r / 255, gamma) + 0.7152 * Math.pow(normal.g / 255, gamma) +
0.0722 * Math.pow(normal.b / 255, gamma);
var inverse = 'black';
if (L < 0.5) {
inverse = 'white';
}
return {'normal': normal, 'inverse': inverse};
};
Stuff.prototype.changeColorValue = function(color_value) {
if (color_value === 255) {
return color_value - this.getRandomInRange(5, 50);
} else if (color_value === 0) {
return color_value + this.getRandomInRange(5, 50);
}
var new_color_value = color_value + this.getRandomInRange(5, 100, true);
if (new_color_value > 255) {
return 255;
} else if (new_color_value < 0) {
return 0;
}
return new_color_value;
};
/* Mutate RGB color by random increment */
Stuff.prototype.changeColor = function(color) {
var normal = {"r": this.changeColorValue(color.normal.r),
"g": this.changeColorValue(color.normal.g),
"b": this.changeColorValue(color.normal.b)};
var gamma = 2.2;
var L = 0.2126 * Math.pow(normal.r / 255, gamma) + 0.7152 * Math.pow(normal.g / 255, gamma) +
0.0722 * Math.pow(normal.b / 255, gamma);
var inverse = 'black';
if (L < 0.5) {
inverse = 'white';
}
return {'normal': normal, 'inverse': inverse};
};
Stuff.prototype.clear = function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
};
Stuff.prototype.getRandomInRange = function(min, max, negative) {
rand = Math.floor(Math.random() * (max - min + 1)) + min;
if (negative) {
if (Math.random() < 0.5) {
rand = rand * -1;
}
}
return rand;
};
Stuff.prototype.sortedInsert = function(ordered_array, value, to_insert) {
for (i = 0; i < ordered_array.length; i++) {
if (ordered_array[i] >= value) {
ordered_array.splice(i, 0, to_insert);
return;
}
}
ordered_array.push(to_insert);
};
Stuff.prototype.lineToNearestPoints = function(context, ordered_array) {
for (i = 0; i < ordered_array.length; i++) {
point = ordered_array[i];
context.beginPath();
context.strokeStyle = 'black';
context.moveTo(point.x, point.y);
if (i !== 0) {
point_before = ordered_array[i-1];
context.lineTo(point_before.x, point_before.y);
}
context.moveTo(point.x, point.y);
if (i !== (ordered_array.length - 1)) {
point_after = ordered_array[i+1];
context.lineTo(point_after.x, point_after.y);
}
context.stroke();
context.closePath();
}
};
Stuff.prototype.initPoints = function(width, height, num_points) {
this.points = [];
for (i = 0; i < num_points; i++) {
random_x = Math.floor(Math.random() * (width + 1));
random_y = Math.floor(Math.random() * (height + 1));
point = {'x': random_x, 'y': random_y};
this.points.push(point);
}
};
Stuff.prototype.distance = function(point1, point2) {
return Math.sqrt(Math.pow((point1.x - point2.x), 2) + Math.pow((point1.y - point2.y), 2));
};
Stuff.prototype.drawPolygon = function(context) {
for (i = 0; i < this.points.length; i++) {
if (this.converge_point) {
var pull_amount = this.getRandomInRange(2, 7, false);
if (this.points[i].x >= this.converge_point.x) {
this.points[i].x = this.points[i].x - pull_amount;
} else {
this.points[i].x = this.points[i].x + pull_amount;
}
if (this.points[i].y >= this.converge_point.y) {
this.points[i].y = this.points[i].y - pull_amount;
} else {
this.points[i].y = this.points[i].y + pull_amount;
}
} else if ((this.mouse_position) && (this.old_mouse_position) && (this.distance(this.mouse_position, this.points[i]) < 50)) {
// var push_amount = this.getRandomInRange(this.mouse_velocity * 0.75, this.mouse_velocity, false);
// if (this.points[i].x >= this.mouse_position.x) {
// this.points[i].x = this.points[i].x + push_amount;
// } else {
// this.points[i].x = this.points[i].x - push_amount;
// }
// if (this.points[i].y >= this.mouse_position.y) {
// this.points[i].y = this.points[i].y + push_amount;
// } else {
// this.points[i].y = this.points[i].y - push_amount;
// }
var push_amount_x = this.old_mouse_position.x - this.mouse_position.x;
var push_amount_y = this.old_mouse_position.y - this.mouse_position.y;
this.points[i].x = this.points[i].x - this.getRandomInRange(push_amount_x * 0.5, push_amount_x * 1.5);
this.points[i].y = this.points[i].y - this.getRandomInRange(push_amount_y * 0.5, push_amount_y * 1.5);
}
if (this.counter % 10 === 0) {
if (Math.random() < 0.5) {
this.points[i].y = this.points[i].y - this.getRandomInRange(3, 6, false);
} else {
this.points[i].y = this.points[i].y + this.getRandomInRange(3, 6, false);
}
} else {
this.points[i].x = this.points[i].x + this.getRandomInRange(0, 2, true);
this.points[i].y = this.points[i].y + this.getRandomInRange(0, 2, true);
}
// this.x_sorted = [];
// this.y_sorted = [];
// this.sortedInsert(this.x_sorted, this.points[i].x, point);
// this.sortedInsert(this.y_sorted, this.points[i].y, point);
context.beginPath();
context.arc(this.points[i].x, this.points[i].y, 1, 0, 2*Math.PI);
context.stroke();
context.closePath();
}
this.converge_point = null;
// this.lineToNearestPoints(context, this.x_sorted);
// this.lineToNearestPoints(context, this.y_sorted);
};
/* Most of this funtion is provided by Maissan Inc. in their tutorial:
http://www.maissan.net/articles/simulating-vines */
Stuff.prototype.drawThing = function(context, sort, prune, chain) {
var AnimationFrame = window.AnimationFrame;
AnimationFrame.shim();
var animationFrame = new AnimationFrame(30);
context.lineWidth = 0.5;
var self = this;
function animate(time) {
// resize canvas if document size changed
dimensions = self.getDocumentDimensions();
if ((dimensions.height !== self.canvas.height) ||
(dimensions.width !== self.canvas.width)) {
self.canvas.height = dimensions.height;
self.canvas.width = dimensions.width;
}
if (self.points === undefined) {
self.initPoints(self.canvas.width, self.canvas.height, self.canvas.width * 1.5);
}
if (!self.paused) {
self.clear();
self.drawPolygon(context);
self.counter = self.counter + 1;
}
frameId = animationFrame.request(animate);
}
// Drawing interval
var frameId = animationFrame.request(animate);
return frameId;
};
Stuff.prototype.canvasClickHandler = function(event) {
var x = event.pageX;
var y = event.pageY;
this.converge_point = {'x': x, 'y': y};
if (this.color) {
this.color = this.changeColor(this.color);
} else {
this.color = this.pickRandomColor();
}
this.canvas.style.backgroundColor = "rgb(" + this.color.normal.r + "," + this.color.normal.g + "," + this.color.normal.b + ")";
this.context.strokeStyle = this.color.inverse;
};
Stuff.prototype.canvasMouseMoveHandler = function(event) {
var x = event.pageX;
var y = event.pageY;
this.old_mouse_position = this.mouse_position;
this.mouse_position = {'x': x, 'y': y};
if (this.old_mouse_position) {
this.mouse_velocity = this.distance(this.mouse_position, this.old_mouse_position);
} else {
this.mouse_velocity = 0.0;
}
};
Stuff.prototype.draw = function() {
var interval_time = 2000;
// Initialize canvas
var dimensions = this.getDocumentDimensions();
this.canvas.height = dimensions.height;
this.canvas.width = dimensions.width;
// Check for canvas support, bind click event, and get context
if (this.canvas.getContext){
var self = this;
this.canvas.addEventListener("click", function () { self.canvasClickHandler.apply(self, arguments); });
this.canvas.addEventListener("mousemove", function () { self.canvasMouseMoveHandler.apply(self, arguments); });
this.context = this.canvas.getContext("2d");
// Draw stuff
var frameId = this.drawThing(this.context, false, true, true);
}
};