# What is the mathematical explanation behind this implementation of simulating eyeballs roll in eyes?

I want to simulate eyeballs roll in eyes and I have found and forked this implementation in codepen.io. This is exactly what I need.

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var border = 10;
var centerX = c.width / 2;
var centerY = c.height / 2;
var radius = 40;

var radiusEye = 12;

var faceCenterX = centerX;
var faceCenterY = border+radius + 60;

var radiusEyeIn = 6;

var eyeYPosition = faceCenterY-8

var reyedx = faceCenterX+(radiusEyeIn/2)+13;
var reyedy = eyeYPosition;

var leyedx = faceCenterX-(radiusEyeIn/2)-13;
var leyedy = eyeYPosition;

var eyesgap = 4;

var eyeXGap = (radiusEye/2)+9;

var reyedxafter = reyedx;
var reyedyafter = reyedy;

var leyedxafter = leyedx;
var leyedyafter = leyedy;

function drawscreen(){

ctx.beginPath();
ctx.arc(faceCenterX, faceCenterY, radius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'rgba(100,100,100,0.5)';
ctx.fill();
ctx.stroke();

var radiusEye = 12;
ctx.beginPath();
ctx.arc(faceCenterX-eyeXGap, eyeYPosition, radiusEye, 0, 2 * Math.PI, false);
ctx.fillStyle = 'rgba(255,255,255,1)';
ctx.fill();
ctx.stroke();

ctx.beginPath();
ctx.arc(faceCenterX+eyeXGap, eyeYPosition, radiusEye, 0, 2 * Math.PI, false);
ctx.fillStyle = 'rgba(255,255,255,1)';
ctx.fill();
ctx.stroke();
}

function draweyes() {

ctx.beginPath();
ctx.arc(reyedxafter, reyedyafter, radiusEyeIn, 0, 2 * Math.PI, false);
ctx.fillStyle = 'rgba(0,0,0,1)';
ctx.fill();

ctx.beginPath();
ctx.arc(leyedxafter, leyedyafter, radiusEyeIn, 0, 2 * Math.PI, false);
ctx.fillStyle = 'rgba(0,0,0,1)';
ctx.fill();
}

//

function mouseMove(e) {
var mouseX = e.pageX - this.offsetLeft - faceCenterX;
var mouseY = e.pageY - this.offsetTop - eyeYPosition;

var ratioX = Math.abs(mouseX)/(Math.abs(mouseX)+Math.abs(mouseY));
var ratioY = Math.abs(mouseY)/(Math.abs(mouseX)+Math.abs(mouseY));

if(mouseX > 0){
reyedxafter = reyedx + (ratioX*eyesgap);
} else {
reyedxafter = reyedx - (ratioX*eyesgap);
}

if(mouseY > 0){
reyedyafter = reyedy + (ratioY*eyesgap);
} else {
reyedyafter = reyedy - (ratioY*eyesgap);
}

if(mouseX > 0){
leyedxafter = leyedx + (ratioX*eyesgap);
} else {
leyedxafter = leyedx - (ratioX*eyesgap);
}

if(mouseY > 0){
leyedyafter = leyedy + (ratioY*eyesgap);
} else {
leyedyafter = leyedy - (ratioY*eyesgap);
}

ctx.clearRect(0, 0, c.width, c.height);
drawscreen();
draweyes();
}

function init() {
// c.addEventListener('mouseup', mouseUp, false);
drawscreen();
draweyes();
}

init();
<canvas id="myCanvas" width="500" height="400" style="border:1px solid #000000;">
</canvas>

I can just use this one but I don't understand the mathematical explanation behind this solution. I can only think of limiting the movement of the eyeballs in the eyes. Why do I have to do it like this one? What is the purpose of calculating ratioX and ratioY? Is there a simpler way to do similar simulation?

• Can you please link the original pen? Commented Jun 24, 2017 at 9:40
• @Bálint I didn't change much: codepen.io/etnepres/pen/aNJQOV?editors=0010. I just make it look nicer. Commented Jun 24, 2017 at 9:51

It's much easier to just get the vectors of the point between the two eyes and the mouse, subtract the face vector from the mouse and normalize the result. The vector you get is the position of the pupils relative to the center of the eyes.

normalize(mouse - face)


You'll need a vector library for this. Without vectors:

x = mouseX - faceX
y = mouseY - faceY
mag = √(x² + y²)
if mag > 0 then
x /= mag
y /= mag

• Wow this is much more succinct. I have my own Vector library but most parts of my game are written without Vectors so I try not to use it too much in the code. So it is just one line of code (with mouse and face positions all converted to vectors)? Commented Jun 24, 2017 at 10:09
• @newguy yeah it is Commented Jun 24, 2017 at 10:45
• What are the x and y in the non-vector version? Are they the relative coordinate to the center of the eyes too? Commented Jun 24, 2017 at 10:50
• @newguy the latter is the translation from vector to vectorless. Yes they are Commented Jun 24, 2017 at 11:00
• Thanks I have made it work: codepen.io/caymanbruce/pen/WOEWwg?editors=0011. One more question though. This method uses square root function while the original one I posted use simple algebra operations. In regards to performance, if I need to roll the pupils a lot in the eyes when playing my game will this approach be slower? Commented Jun 24, 2017 at 11:07