Click here to Skip to main content
Licence CPOL
First Posted 9 Jan 2012
Views 9,338
Bookmarked 6 times

HTML5 Eyes that follow the mouse

By | 9 Jan 2012 | Technical Blog
I made a cute flash movie of an elephant ages ago. Among other things the eyes of the elephant followed the cursor. Unfortunately subsequent flash security updates broke the functionality (if you want mouse move events outside the flash control … Continue reading →
A Technical Blog article. View original blog here.[^]

NellyI made a cute flash movie of an elephant ages ago. Among other things, the eyes of the elephant followed the cursor. Unfortunately subsequent flash security updates broke the functionality (if you want mouse move events outside the flash control, you need special permissions). So, I decided to convert it to HTML5. To see the result in action you need to go to the origonal blog entry.

How It’s Done 

I use an onload event handler somewhere in the HTML file which calls the init() function. E.g.:

<body onload="init()">

In the init() function, the images are loaded and the canvas resized and then the render loop is started via requestAnimFrame. All images are stored in the one PNG (this is known as an image atlas).

function init()
{
  canvas = document.getElementById('nelly');
  if (canvas.getContext)
  {
    context = canvas.getContext('2d');
  }
  else
  {
    return;
  }
  logElement = document.getElementById('log');
  atlas = new Image();  
  atlas.src = 'http://astronautz.com/wordpress/nelly0.png';
  atlas.onload = function()
  { 
    window.addEventListener ("mousemove", getCoords, true);
    xCanvas = canvas.offsetLeft;
    yCanvas = canvas.offsetTop;
    var elem = canvas.offsetParent;
    while (elem)
    {
      xCanvas += elem.offsetLeft;
      yCanvas += elem.offsetTop;
      elem = elem.offsetParent;
    }

    backWidth = 97;
    backHeight = 150;
    canvas.width = backWidth;
    canvas.height = backHeight;
    eyeRight.setSize(4, 4);
    eyeRight.setMin(44, 30);
    eyeRight.setMax(54, 52);
    eyeRight.setAtlas(97, 0);
    eyeRight.init();
    eyeLeft.setSize(4, 4);
    eyeLeft.setMin(34, 30);
    eyeLeft.setMax(39, 52);
    eyeLeft.setAtlas(97, 0);
    eyeLeft.init();
    requestAnimFrame(render);
  };  
}

Note that I create an event handler which stores the mouse coordinates in two global variables:

var xMouse = 0;
var yMouse = 0;
...
function getCoords(event) 
{
  xMouse = event.clientX;
  yMouse = event.clientY + window.pageYOffset;
};
...
window.addEventListener ("mousemove", getCoords, true);

Each eye is controlled by an Eye object. It takes a min, max as parameters:


It also needs the size of the eye image and its position within the image atlas before you initialise:

eyeRight.setSize(4, 4);
eyeRight.setMin(44, 30);
eyeRight.setMax(54, 52);
eyeRight.setAtlas(97, 0);
eyeRight.init();

The eye movement is calculated by getting the slope of the angle between the eyeball center and the current mouse position. Then you need to calculate the position taking into account the quadrant:

this.update = function()
  {
    var xDiff = xMouse-(xCanvas+this.m_xOrig);
    var yDiff = yMouse-(yCanvas+this.m_yOrig);
    if (yDiff == 0)
    {
      if (xDiff > 0)
      {
        this.m_x = this.m_xMax;
      }
      else
      {
        this.m_x = this.m_xMin;
      }
      this.m_y = this.m_yOrig;
    }
    else
    {
      var slope = xDiff/yDiff;
      if (yDiff > 0)
      {
        this.m_x = slope*(this.m_xMax-this.m_xMin) + this.m_xMin;
      }
      else
      {
        this.m_x = -slope*(this.m_xMax-this.m_xMin) + this.m_xMin;
      }
    }
    if (xDiff == 0)
    {
      if (yDiff > 0)
      {
        this.m_y = this.m_yMax;
      }
      else
      {
        this.m_y = this.m_yMin;
      }
      this.m_x = this.m_xOrig;
    }
    else
    {
      var slope = yDiff/xDiff;
      if (xDiff > 0)
      {
        this.m_y = slope*(this.m_yMax-this.m_yMin) + this.m_yMin;
      }
      else
      {
        this.m_y = -slope*(this.m_yMax-this.m_yMin) + this.m_yMin;
      }
    }
    if (this.m_x > this.m_xMax)
    {
      this.m_x = this.m_xMax;
    }
    else if (this.m_x < this.m_xMin)
    {
      this.m_x = this.m_xMin;
    }
    if (this.m_y > this.m_yMax)
    {
      this.m_y = this.m_yMax;
    }
    else if (this.m_y < this.m_yMin)
    {
      this.m_y = this.m_yMin;
    }
  }

The full source code can be downloaded here.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

ed welch

Software Developer
Astronautz
Spain Spain

Member

After working in the software industry for many years, I've started my own games company that specialises in strategy games for mobile platforms.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralMy vote of 5 PinmemberFlorian.Witteler23:54 16 Jan '12  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web03 | 2.5.120517.1 | Last Updated 9 Jan 2012
Article Copyright 2012 by ed welch
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid