Home > Articles > Web Development > HTML/CSS

  • Print
  • + Share This
This chapter is from the book

1.5. Fundamental Drawing Operations

In the next chapter we will look closely at drawing in a canvas. For now, however, to familiarize you with the drawing methods that the Canvas API provides, let’s begin with the application shown in Figure 1.13, which implements an analog clock.

Figure 1.13

Figure 1.13. A clock

The clock application, which is listed in Example 1.4, uses the following drawing methods from the Canvas API:

  • arc()
  • beginPath()
  • clearRect()
  • fill()
  • fillText()
  • lineTo()
  • moveTo()
  • stroke()

Like Adobe Illustrator and Apple’s Cocoa, Canvas lets you draw shapes by creating invisible paths that you subsequently make visible with calls to stroke(), which strokes the outline of the path, or fill(), which fills the inside of the path. You begin a path with the beginPath() method.

The clock application’s drawCircle() method draws the circle representing the clock face by invoking beginPath() to begin a path, and subsequently invokes arc() to create a circular path. That path is invisible until the application invokes stroke(). Likewise, the application’s drawCenter() method draws the small filled circle at the center of the clock with a combination of beginPath(), arc(), and fill().

The application’s drawNumerals() method draws the numbers around the face of the clock with the fillText() method, which draws filled text in the canvas. Unlike the arc() method, fillText() does not create a path; instead, fillText() immediately renders text in the canvas.

The clock hands are drawn by the application’s drawHand() method, which uses three methods to draw the lines that represent the clock hands: moveTo(), lineTo(), and stroke(). The moveTo() method moves the graphics pen to a specific location in the canvas, lineTo() draws an invisible path to the location that you specify, and stroke() makes the current path visible.

The application animates the clock with setInterval(), which invokes the application’s drawClock() function once every second. The drawClock() function uses clearRect() to erase the canvas, and then it redraws the clock.

Example 1.4. A basic clock

var canvas = document.getElementById('canvas'),
    context = canvas.getContext('2d'),
    FONT_HEIGHT = 15,
    MARGIN = 35,
    HAND_TRUNCATION = canvas.width/25,
    HOUR_HAND_TRUNCATION = canvas.width/10,
    NUMERAL_SPACING = 20,
    RADIUS = canvas.width/2 - MARGIN,
    HAND_RADIUS = RADIUS + NUMERAL_SPACING;

// Functions..........................................................

function drawCircle() {
   context.beginPath();
   context.arc(canvas.width/2, canvas.height/2,
               RADIUS, 0, Math.PI*2, true);
   context.stroke();
}

function drawNumerals() {
   var numerals = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ],
       angle = 0,
       numeralWidth = 0;

   numerals.forEach(function(numeral) {
      angle = Math.PI/6 * (numeral-3);
      numeralWidth = context.measureText(numeral).width;
      context.fillText(numeral,
         canvas.width/2 + Math.cos(angle)*(HAND_RADIUS) -
            numeralWidth/2,
         canvas.height/2 + Math.sin(angle)*(HAND_RADIUS) +
            FONT_HEIGHT/3);
   });
}
function drawCenter() {
   context.beginPath();
   context.arc(canvas.width/2, canvas.height/2, 5, 0, Math.PI*2, true);
   context.fill();
}

function drawHand(loc, isHour) {
   var angle = (Math.PI*2) * (loc/60) - Math.PI/2,
      handRadius = isHour ? RADIUS - HAND_TRUNCATION-HOUR_HAND_TRUNCATION 
                          : RADIUS - HAND_TRUNCATION;

   context.moveTo(canvas.width/2, canvas.height/2);
   context.lineTo(canvas.width/2 + Math.cos(angle)*handRadius,
                  canvas.height/2 + Math.sin(angle)*handRadius);
   context.stroke();
}

function drawHands() {
   var date = new Date,
       hour = date.getHours();

   hour = hour > 12 ? hour - 12 : hour;

   drawHand(hour*5 + (date.getMinutes()/60)*5, true, 0.5);
   drawHand(date.getMinutes(), false, 0.5);
   drawHand(date.getSeconds(), false, 0.2);
}

function drawClock() {
   context.clearRect(0,0,canvas.width,canvas.height);

   drawCircle();
   drawCenter();
   drawHands();
   drawNumerals();
}

// Initialization................................................

context.font = FONT_HEIGHT + 'px Arial';
loop = setInterval(drawClock, 1000);
  • + Share This
  • 🔖 Save To Your Account