var stage, balls, eigens, components = [];
var xBar = 0,
yBar = 0;
var needsUpdate = false;
/*
* runs when index.html is fully loaded
*/
window.onload = function () {
//initialize stage object, where "canvas" references the id of our canvas
stage = new createjs.Stage("canvas");
stage.stageWidth = 600;
stage.stageHeight = 400;
//create black background
bg = new createjs.Shape();
bg.graphics.beginFill("#000");
bg.graphics.moveTo(0, 0);
bg.graphics.lineTo(stage.stageWidth, 0);
bg.graphics.lineTo(stage.stageWidth, stage.stageHeight);
bg.graphics.lineTo(0, stage.stageHeight);
bg.graphics.endFill();
stage.addChild(bg);
// Principal Component line containers
components.push(new createjs.Shape());
components.push(new createjs.Shape());
stage.addChild(components[0]);
stage.addChild(components[1]);
//populate balls
balls = [];
for (var i = 0; i < 9; i++) {
// initialize ball object
var ball = new createjs.Shape();
// select ball color to be red.
ball.graphics.beginFill("#ff3333");
// draw circle of radius 5 at position (0, 0) relative to the ball's
// coordinates
ball.graphics.drawCircle(0, 0, 5);
// set ball object's coordinates
var randTemp = (Math.random() - 0.5);
ball.x = stage.stageWidth / 2 + randTemp * 200;
ball.y = stage.stageHeight / 2 - randTemp * 200;
// add our ball to stage so that it actually gets drawn.
// (this needs to be done only once per object)
stage.addChild(ball);
ball.onPress = pressHandler;
balls.push(ball);
}
// draw all shapes to canvas
stage.update();
// set framerate to 30FPS
createjs.Ticker.setFPS(30);
// call tick(event) on every "tick"
createjs.Ticker.addEventListener("tick", tick);
updateEigen();
};
/*
* called every frame (30 times per second)
*/
function tick() {
if (needsUpdate) {
for (var i = 0; i <= 1; i++) {
components[i].graphics.clear();
components[i].graphics.setStrokeStyle(2);
components[i].graphics.beginStroke(createjs.Graphics.getRGB(Math.random() * 255 | 0, Math.random() * 255 | 0, Math.random() * 255 | 0));
components[i].graphics.moveTo(xBar - eigens.E.x[0][i] * Math.sqrt(eigens.lambda.x[i]), yBar - eigens.E.x[1][i] * Math.sqrt(eigens.lambda.x[i]));
components[i].graphics.lineTo(xBar + eigens.E.x[0][i] * Math.sqrt(eigens.lambda.x[i]), yBar + eigens.E.x[1][i] * Math.sqrt(eigens.lambda.x[i]));
needsUpdate = false;
}
}
// draw all shapes to canvas
stage.update();
}
// At the press of a ball
function pressHandler(e) {
e.onMouseMove = function (ev) {
if (e !== undefined) {
e.target.x = ev.stageX;
e.target.y = ev.stageY;
update = true;
}
updateEigen();
};
}
// recalculates eigenvalues/vectors
function updateEigen() {
var xs = [];
var ys = [];
for (var i = 0; i < balls.length; i++) {
var ball = balls[i];
xs.push(ball.x);
ys.push(ball.y);
}
xBar = numeric.sum(xs) / xs.length;
yBar = numeric.sum(ys) / ys.length;
for (var i = 0; i < xs.length; i++) {
xs[i] -= xBar;
}
for (var i = 0; i < ys.length; i++) {
ys[i] -= yBar;
}
var matrix = [xs, ys];
//console.log(xs);
//console.log(ys);
matrix = numeric.dotMMsmall(matrix, numeric.transpose(matrix));
matrix[0][0] /= xs.length;
matrix[1][0] /= xs.length;
matrix[1][1] /= xs.length;
matrix[0][1] /= xs.length;
//console.log(matrix)
eigens = numeric.eig(matrix);
//console.log(eigens);
needsUpdate = true;
}
External resources loaded into this fiddle: