Procedural Eye Generator
by Santiago J
CSS
html, body {
background-color: #333;
color: #eee;
margin: 0;
padding: 0;
}
canvas {
background-color: #000;
color: #fff;
display: block;
margin: 16px auto 0;
outline: 1px solid #555;
}
JavaScript
// Auxiliary functions
function dist(x1, y1, x2, y2, sq) {
x2 -= x1;
y2 -= y1;
return sq ? x2*x2 + y2*y2 : Math.sqrt(x2*x2 + y2*y2);
}
function dist2(a1, a2) {
return dist(a1[0], a1[1], a2[0], a2[1]);
}
function getCircle(x1, y1, x2, y2, x3, y3, d) {
var x1_, y1_, x2_, y2_, m1, b1, m2, b2, xc, yc, r;
if (y1 === y2 && y2 === y3) {
return false;
}
// get 2 midpoints
x1_ = (x1 + x2) / 2;
y1_ = (y1 + y2) / 2;
x2_ = (x2 + x3) / 2;
y2_ = (y2 + y3) / 2;
if (y1 === y2) {
xc = x1_;
} else {
m1 = (x1 - x2) / (y2 - y1);
b1 = y1_ - m1 * x1_;
}
if (y2 === y3) {
xc = x2_;
} else {
m2 = (x2 - x3) / (y3 - y2);
b2 = y2_ - m2 * x2_;
}
if (!xc) {
if (m1 === m2) {
return false;
}
xc = (b2 - b1) / (m1 - m2);
}
yc = m1 ? m1 * xc + b1 : m2 * xc + b2;
if (typeof d === "function") {
r = d(xc, yc, x1, y1);
} else {
m1 = xc - x1; // reusing variables
m2 = yc - y1; // for radius calculation.
r = Math.sqrt(m1*m1 + m2*m2);
}
return {x: xc, y: yc, r: r};
}
// Config
var params = {};
params.w = 800; // canvas width
params.h = 600; // canvas height
// Set up canvas and methods
var c = document.createElement("canvas").getContext("2d");
c.canvas.width = params.w;
c.canvas.height = params.h;
c.fillStyle = "#fff";
c.strokeStyle = "#000";
document.body.appendChild(c.canvas);
c.fillCircle = function(x, y, r) {
this.beginPath();
this.arc(x, y, r, 0, 6.2832, false);
this.fill();
};
c.strokeCircle = function(x, y, r) {
this.beginPath();
this.arc(x, y, r, 0, 6.2832, false);
this.stroke();
};
c.spline = function(p, t, de) {
var j = p.length;
if (j < 2) {
if (j === 1) {
this.fillCircle(p[0][0], p[0][1], 2);
}
return false;
}
if (!t) { t = 3; }
var cc, cp1, cp2, cp_last = p[0], d, d2 = dist2(p[1], p[0]) / t, i;
this.beginPath();
this.moveTo(p[0][0], p[0][1]);
for (i = 1; i < j; i++) {
// Get control points
if...