Click here to Skip to main content
15,885,767 members
Articles / Web Development / HTML

HTML5 Eyes that Follow the Mouse

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
9 Jan 2012CPOL1 min read 24.7K   6   1
HTML5 Eyes that follow the mouse

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 original blog entry.

How It’s Done 

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

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

JavaScript
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:

JavaScript
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:

JavaScript
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:

JavaScript
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)


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

Comments and Discussions

 
GeneralMy vote of 5 Pin
Florian.Witteler16-Jan-12 23:54
Florian.Witteler16-Jan-12 23:54 

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

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