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...