Friday, September 27, 2013

Eyes in canvas + javascript

The students web/javascript needed a new small exercise to learn how to play with a canvas.

What would be better than the old X eyes? The eyes following your cursor...



How to calculate where to put the inner eye



// pos1X,Y is the middle of the eye in global coordinates
var dx = cursorX - this.pos1X; 
var dy = cursorY - this.pos1Y;

var distance = Math.sqrt(dx*dx+dy*dy);

var x = (distance < this.radius)? dx : dx*this.radius/distance;
var y = (distance < this.radius)? dy : dy*this.radius/distance;

// eye1X,Y is the middle of the eye in canvas coordinates
this.drawEye(this.eye1X+x, this.eye1Y+y);



The complete code, have fun:


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset=utf-8>
  <script src="../lib/jquery.js"></script>
  <style> body { text-align: center }</style>
  <title>HTML5 Demo: Canvas with Eyes</title>
  <script>
    window.onload = function() {

      var eyes = {

        drawEye: function (x, y) {
          this.ctx.beginPath();
          this.ctx.arc(x, y, this.radius, 0, 2*Math.PI, false);
          this.ctx.fill();
          this.ctx.closePath();
        },

        drawSmiley: function () {
          // clear the canvas
          this.canvas.width = this.canvas.width;

          // The large circle
          this.ctx.beginPath();
          this.ctx.arc(this.midX,this.midY,this.midX-2,0,Math.PI*2,true);   

          // The mount drawn clockwise
          var mouthR = Math.floor(this.midX * 2 / 3);
          this.ctx.moveTo(this.midX+mouthR,this.midY);
          this.ctx.arc(this.midX,this.midY,mouthR,0,Math.PI,false);

          // first eye
          this.ctx.moveTo(this.eye1X+this.outline,this.eye1Y);
          this.ctx.arc(this.eye1X,this.eye1Y,this.outline,0,Math.PI*2,true);  

          // second eye
          this.ctx.moveTo(this.eye2X+this.outline,this.eye2Y);
          this.ctx.arc(this.eye2X,this.eye2Y,this.outline,0,Math.PI*2,true);

          this.ctx.stroke();
        },

        lookAt: function(cursorXcursorY) {
          // calc global position for comparing with the mouse position
          var pos1X = this.eye1X + this.canvas.offsetLeft;
          var pos1Y = this.eye1Y + this.canvas.offsetTop;

          var pos2X = this.eye2X + this.canvas.offsetLeft;
          var pos2Y = this.eye2Y + this.canvas.offsetTop;

          // first eye
          var dx = cursorX - pos1X;
          var dy = cursorY - pos1Y;
          var distance = Math.sqrt(dx*dx+dy*dy);
          var x = (distance < this.radius)? dx : dx*this.radius/distance;
          var y = (distance < this.radius)? dy : dy*this.radius/distance;
          this.drawEye(this.eye1X+x, this.eye1Y+y);

          // second eye
          dx = cursorX - pos2X;
          dy = cursorY - pos2Y;
          distance = Math.sqrt(dx*dx+dy*dy);
          x = (distance < this.radius)? dx : dx*this.radius/distance;
          y = (distance < this.radius)? dy : dy*this.radius/distance;
          this.drawEye(this.eye2X+x, this.eye2Y+y);
        },

        init: function(theCanvas) {
          // get a drawing context
          this.canvas = theCanvas;
          this.ctx = theCanvas.getContext("2d");

          // calculate the middle of the canvas
          this.midX = Math.floor(this.canvas.width / 2);
          this.midY = Math.floor(this.canvas.height / 2);

          // calculate the middle of the 2 eyes  on 1/3 and 2/3 of the canvas
          this.eye1X = Math.floor(this.canvas.width * 1 / 3);
          this.eye1Y = Math.floor(this.canvas.height * 2 / 5);
          this.eye2X = Math.floor(this.canvas.width * 2 / 3);
          this.eye2Y = this.eye1Y;

          // radius = iris, outline = total eye
          this.radius = this.canvas.width / 20;
          this.outline = this.radius * 2;
        }
      };

      eyes.init( document.getElementById("eyes") );
      eyes.drawSmiley();
      document.onmousemove = function(evt) {
        eyes.drawSmiley();
        eyes.lookAt(evt.clientX, evt.clientY);
      };
    };

  </script>
</head>
<body>
    <header>
      <h1>Canvas</h1>
    </header>

    <canvas width=200 height=200 id=eyes></canvas>

  <p>Wie kijkt naar waar?</p>
</body>
</html>