In this little tutorial I’m going to show you how to create a small jQuery code where 2 eyes follow mouse movement. Its basically a fetches the mouse position on screen and calculates the css top and left attributes that are appropriate for the eyeball by keeping it inside the eye container, theres a little math involved so its gonna be fun
Demo
download
you can download it or fork it from github here , or get it directly from here.
HTML and CSS
nothing weird or complex in the html, just two DIVs for the eyeballs and one DIV for the face with 2 eyes containers inside
1 2 3 4 5 6 | <div class='eyeBall' id='eyeBall_1'></div> <div class='eyeBall' id='eyeBall_2' ></div> <div class='face'> <div class='eyeContainer' rel='1'></div> <div class='eyeContainer' rel='2'></div> </div> |
In css I used border radius to make the divs look rounded like a circle for both the eye container and face (outer container) and used absolute position for the eyeballs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | .face { border: 1px solid black; width: 100px; height: 100px; border-radius: 60px; margin: 0 auto; } .eyeContainer { border: 1px solid black; width: 25px; height: 25px; border-radius: 60px; float: left; margin-top: 16px; margin-left: 15px; } .eyeBall { border: 1px solid black; background: black; width: 5px; height: 5px; border-radius: 60px; float: left; margin-top: 9px; margin-left: 9px; position: absolute; } |
How to

The whole idea is about getting the correct left and top css attributes for the eye ball position, to do this we need to:
- get current mouse position and the position of the eye container center
- calculate the distance between these two points
- find the distance between the mouse position and the eye container radius, this is necessary to make the eye ball inside the eye container without going outside the border.
- after finding the distance we can easily calculate the top and left of the point with simple math.
1 2 3 4 5 6 7 8 | jQuery(document).ready(function() { jQuery(document).mousemove(function(e) { var mousePosition = { 'x' : e.pageX, 'y' : e.pageY }; }); }); |
1 2 3 4 5 6 7 | jQuery(".eyeContainer").each(function(i, i2) { var eyeContainerPosition = $(this).offset(); var eyePosition = { 'x' : eyeContainerPosition.left + $(this).width() / 2 +1, 'y' : eyeContainerPosition.top + $(this).height() / 2 +1 } }); |
2. now we got the two points we can just get the distance between them using this simple formula
in javascript this means:
1 2 3 4 5 6 7 | function getDistance(loc1, loc2) { return Math.sqrt( Math.pow((loc1.x - loc2.x), 2) + Math.pow((loc1.y - loc2.y), 2) ); } |
3. to find the distance between the mouse position and the first point on the eye container radius we minus eye container half diameter from the distance between the eye center and mouse.
1 2 | var toCenterdistance = getDistance(eyePosition, mousePosition); var targetDistance = toCenterdistance - ($(this).width() / 2); |
4. Till now we got the distance between the mouse position and the nearest point on the eye container radius, after googling around I found out that using the slope of the line we can get any point on the line given the distance in trigonometry we can use this:
1 2 | x = r cos (theta) y = r sin (theta) |
where r is the distance we already got, and theta is the angle; which can be found by getting the arctangent of the slope(y/x). in javascript this means:
1 2 3 | var slope = getSlope(eyePosition, mousePosition); var x = Math.cos( Math.atan(slope) ) * targetDistance; var y = Math.sin(Math.atan(slope)) * targetDistance; |
this gets good results but still needs a little modification to work. the x and y values are relevant to the eye center to get the correct position we need to do the following
1 2 3 4 5 | if(eyePosition.x > mousePosition.x) { x += mousePosition.x; } else if(eyePosition.x < mousePosition.x) { x = -x + mousePosition.x; } |
now this will work fine and eyeball position will be correct and always on eye container radius, but what if the mouse cursor was inside the eye container itself?? this image explains it
as you can see the eye ball should be on the tip of the mouse cursor but instead its on the eye container radius as its supposed to be, to fix this all we need to do is to check if the distance between the cursor and the eye container is less or equal to the eye container half diameter. so the final code for getting the left and top css attributes is
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | if(toCenterdistance > ($(this).width() / 2)) { var x = Math.cos(Math.atan(slope)) * targetDistance; if(eyePosition.x > mousePosition.x) { x += mousePosition.x; } else if(eyePosition.x < mousePosition.x) { x = -x + mousePosition.x; } var y = Math.sin(Math.atan(slope)) * targetDistance; if(eyePosition.x > mousePosition.x) { y += mousePosition.y; } else if(eyePosition.x < mousePosition.x) { y = -y + mousePosition.y; } x -= $(this).height() / 2; y -= $(this).height() / 2; } else { x = mousePosition.x - ($(this).width() / 2); y = mousePosition.y - ($(this).width() / 2); } var element=$("#eyeBall_" + $(this).attr("rel")); element.css({ 'left' : x + 'px', 'top' : y + 'px', }); |
Well, thats all :{D . let me know if there’s an easier way or something to add in the comments below

