Drawing a Logo

0
193

The canvas element is a container element much like the script element. It’s a blank slate we can draw on. We define a canvas with a width and height like this:

<canvas id=”my_canvas” width=”150″ height=”150″>
Fallback content here
</canvas>

Unfortunately, you can’t use CSS to control or alter the width and height of a canvas element without distorting the contents, so you need to decide on your canvas dimensions when you  declare it.

We use JavaScript to put shapes on the canvas. Even if you provided fallback content to those browsers without the canvas element, you still need to prevent the JavaScript code from trying to manipulate it. Find the canvas by its ID, and see whether the browser supports the canvas’ getContext method.

var canvas = document.getElementById(‘my_canvas’);
if (canvas.getContext){
var context = canvas.getContext(‘2d’);
}else{
// do something to show the canvas’ hidden contents
// or let the browser display the text within the <canvas> element.
}

If we get a response from the getContext method, we grab the 2D context for the canvas so we can add objects. If we don’t have a context, we need to devise a way to display the fallback content. Since we know that the canvas element requires JavaScript in order to work, we’re building a framework to handle fallbacks from the beginning.

Once you have the canvas’ context, you simply add elements to that context. To add a red box, you set the fill color and then create the box, like this:

 

context.fi 11 Style = “rgb(200,0,0)” ;
context.fillRect (10, 10, 100, 100);

The canvas’s 2D context is a grid, with the top-left corner as the default origin. When you create a shape, you specify the starting X and Y coordinates and the width and height.

Each shape is added onto its own layer, so you could create three boxes with a 10-pixel offset, like this:

context, f i l l Style = “rgb(200,0,0)”;
context. fillRect (10, 10, 100, 100);
context.fill Style = “rgb(0,200,0)”;
context.fillRect (20, 20, 100, 100);
context.fill Style = “rgb(0,0,200)”;
context.fillRect (30, 30, 100, 100);

and they’ll stack on top of each other, like this:

Now that you have an understanding of the basics of drawing, let’s put together the AwesomeCo logo. It’s pretty simple, as you can see from Figure 6.1, on the following page.

Drawing the Logo

The logo consists of a string of text, an angled path, a square, and a triangle. Let’s start by creating a new HTML5 document, adding a canvas element to the page, and then creating a JavaScript function for drawing the logo, which detects whether we can use the 2D canvas.

var drawLogo = function(){
var canvas = document.getElementByld(‘logo’);
var context = canvas.getContext(‘2d’);
};

We invoke this method after first checking for the existence of the canvas
element, like this:

$(function(){
var canvas = document.getElementByld(‘logo’);
if (canvas.getContext){
drawLogo() ;
}

Notice here we’re using the j Query function again to ensure that the
event fires when the document is ready. We’re looking for an element
on the page with the ID of logo, so we’d better make sure we add our
canvas element to the document so it can be found, and our detection
will work.

 

<canvas id=”logo” width=”900″ height=”80″>
<hl>AwesomeCo</hl>
</canvas>

 

Next, let’s add the “AwesomeCo” text to the canvas.

Adding Text

Adding text to the canvas involves choosing a font, a font size, and an
alignment, and then applying the text to the appropriate coordinates
on the grid. We can add the text “AwesomeCo” to our canvas like this:

context.font = ‘italic 40px sans-serif’;
context.textBaseline = ‘top’;
context.fillTextC’AwesomeCo’, 60, 0);

We’re defining the text type and setting its baseline, or vertical alignment,
before we apply it to the canvas. We’re using the fillText method
so we get text that’s filled in with the fill color, and we’re setting it 60
pixels to the right so we can make room for the large triangle-shaped
path we’ll draw next.

Drawing Lines

We draw lines on the canvas by playing a game of “connect-the-dots.”
We specify a starting point on the canvas grid and then specify additional
points on the grid to move to. As we move around the canvas, the
dots get connected, like this:

Drawing LinesWe use the beginPathO method to start drawing a line, and then we
create our path, like this:

context.lineWidth = 2;
context.begi nPath Q;
context.moveTo(0, 40);
context.lineTo(30, 0);
context.lineTo(60, 40 );
context.lineTo(285, 40 );
context. strokeO ;
context.closePathQ ;

When we’re all done moving around the canvas, we have to call the
stroke method to draw the line and then call the closePath method to
stop drawing.
Now all that’s left is the box and triangle combination that sits within
the big triangle.

Moving the Origin

We need to draw a small square and triangle inside the larger triangle.
When we draw shapes and paths, we can specify the X and Y coordinates
from the origin at the top-left corner of the canvas, but we can
also just move the origin to a new location.
Let’s draw the smaller inner square by moving the origin.

context.save();
context.translate(20,20) ;
context.fillRect(0,0,20,20);

Notice that before we move the origin, we call the save() method. This
saves the previous state of the canvas so we can revert easily. It’s like
a restore point, and you can think of it as a stack. Every time you
call save(), you get a new entry. When we’re all done, we’ll call restoreO,
which will restore the top savepoint on the stack.

Now let’s use paths to draw the inner triangle, but instead of using a
stroke, we’ll use a fill to create the illusion that the triangle is “cutting
into” the square.

context.fi11 Style = ‘#fff’;
context.strokeStyle = ‘#fff’;
context.lineWidth = 2;
context.beginPathO ;
context.moveTo(0, 20);
context.lineTo(10, 0);
context.lineTo(20, 20 ) ;
context.lineTo(0, 20 );
context.fi11();
context.closePathO ;
context. restoreO ;

Here we set the stroke and fill to white (#fff) before we begin drawing.
Then we draw our lines, and since we moved the origin previously, we’re
relative to the top-left corner of the square we just drew.

We’re almost done, but it needs a little color.

Adding Colors

In Section 13, Moving the Origin, on the previous page, you saw briefly
how to set the stroke and fill color for the drawing tools. We could set
the color of everything to red just by adding this code before we draw
anything:

context.fi11 Style = “#fOO”;
context.strokeStyle = “#fOO”;

But that’s a little boring. We can create gradients and assign those to
strokes and fills like this:

// context.fi11 Style = “#fOO”;
// context.strokeStyle = “#fOO”;
var gradient = context.createLinearGradient(0, 0, 0, 40);
gradient.addColorStopCO, ‘#a00’); // red
gradient.addColorStop(l, ‘#f00’); // red
context.fi11 Style = gradient;
context.strokeStyle = gradient;

We just create a gradient object and set the color stops of the gradient.
In this example, we’re just going between two shades of red, but we
could do a rainbow if we wanted.2

Note that we have to set the color of things before we draw them.
At this point, our logo is complete, and we have a better understanding
of how we draw simple shapes on the canvas. However, versions of
Internet Explorer prior to IE9 don’t have any support for the canvas
element. Let’s fix that.

Falling Back

Google released a library called ExplorerCanvas3 that makes most of
the Canvas API available to Internet Explorer users. All we have to do
is include this library on our page:

<! — [ i f lte IE 8]>
<script src=”javascripts/excanvas.js”x/script>
<![endif]–>

and things should work just fine in Internet Explorer—but they don’t
work just yet. At the time of writing, the most stable release doesn’t support
adding text at all, and the version from the Subversion repository4
doesn’t use the correct fonts. Also, there’s no support yet for adding
gradients on strokes with this library.

So, instead, we rely on other solutions, such as placing a PNG of the
logo inside the canvas element, or we simply don’t use the canvas at all.
Since this was just an exercise to show you how to draw, it’s not the end
of the world if we can’t use this particular example in a cross-platform
production system yet.