Zion curve

by Mikel Ortega

HTML

<canvas id="photo" width=500 height=500 style="position: absolute;"></canvas>
<canvas id="graph" width=500 height=500 style="position: absolute;"></canvas>
<canvas id="anim" width=500 height=500 style="position: absolute;"></canvas>

JavaScript

var photo_canvas = document.getElementById('photo'),
    photo_ctx = photo_canvas.getContext('2d');
var canvas = document.getElementById('graph'),
    ctx = canvas.getContext('2d');
var anim_canvas = document.getElementById('anim'),
    anim_ctx = anim_canvas.getContext('2d');
var img = new Image();

img.onload = start;
img.src = 'http://farm4.staticflickr.com/3764/11007136095_45c3abaeba.jpg';

function start() {
    photo_ctx.drawImage(img, 0, 0, photo.width, photo.height);
    anim_canvas.onmousemove = updateLine;
    drawFixedGraph();
}

function MagicCurve(y) {
    return (y * y - y + 0.15) * (-0.65) * Math.cos(1.17 / (y-0.1)) - 0.30;
}

function photoX(x) {
    return (1.0 + x) * 0.5 * photo.width;
}

function photoY(y) {
    return (1.0 - y) * 0.5 * photo.height;
}

function drawFixedGraph() {
    ctx.beginPath();
    ctx.strokeStyle = '#fff';
    ctx.lineCap = 'square'
    ctx.lineWidth = 3;
    for (var y = -1.0; y < 1.0; y = y + 0.01) {

        var x = MagicCurve(y);

    ctx.lineWidth = 2;
    ctx.strokeStyle = '#555';
        ctx.lineTo(photoX(x), photoY(y));
        ctx.stroke();
    ctx.lineWidth = 1;
    ctx.strokeStyle = '#fff';
        
        ctx.lineTo(photoX(x), photoY(y));
        ctx.stroke();
    }
    ctx.lineWidth = 1;
    ctx.moveTo(photoX(-1), photoY(0));
    ctx.lineTo(photoX(1), photoY(0));
    ctx.moveTo(photoX(0), photoY(-0.8));
    ctx.lineTo(photoX(0), photoY(1));
    ctx.font="18px Courier";
    ctx.strokeText("X = (Y^2+Y+a)*b*cos(c/(Y+d))+e",photoX(-0.4), photoY(-0.9));
    ctx.stroke();
}

function updateLine(e) {
    var r = anim_canvas.getBoundingClientRect();
    var gy = e.clientY - r.top;
    var y = -2.0 * gy / photo.height + 1.0;

    var x = MagicCurve(y);

    anim_ctx.clearRect(0, 0, canvas.width, canvas.height);
    anim_ctx.beginPath();
    anim_ctx.strokeStyle = '#fff';
    anim_ctx.lineWidth = 1;
    anim_ctx.font="18px Courier";
    anim_ctx.strokeText("X = " + x.toFixed(2).toString(), photoX(0.3),...