Drawing graphics with canvas

  • Revision slug: HTML/Canvas/Drawing_Graphics_with_Canvas
  • Revision title: Drawing Graphics with Canvas
  • Revision id: 75276
  • Created:
  • Creator: VladVukicevic
  • Is current revision? No
  • Comment

Revision Content

Introduction

With the Firefox 1.1 Developer Preview Release, Firefox includes a new HTML element for programmable graphics. <tt><canvas></tt> is based on [WhatWG canvas specification], which itself is based on Apple's <tt><canvas></tt> implemented in Safari. It can be used for rendering graphs, UI elements, and other custom graphics on the client.

<tt><canvas></tt> creates a fixed size drawing surface that exposes one or more rendering contexts. We'll focus on the 2D rendering context (incidentally, the only currently defined rendering context). In the future, other contexsts may provide different types of rendering; for example, a 3D context based on OpenGL ES.

The 2D Rendering Context

A Simple Example

To start off, here's a simple example that draws two intersecting rectangles, one of which has alpha transparency:

Example 1.

<html>
 <head>
  <script type="application/x-javascript">
function onload() {
 var canvas = document.getElementById("canvas");
 var ctx = canvas.getContext("2d");

 ctx.fillStyle = "rgb(200,0,0)";
 /* fillRect 
 ctx.fillRect (10, 10, 50, 50);

 ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
 ctx.fillRect (30, 30, 50, 50);
}
  </script>
 </head>
 <body onload="onload()">
   <canvas id="canvas" width="300" height="300">
 </body>
</html>

The <tt>draw</tt> function gets the <tt>canvas</tt> element, then obtains the <tt>2d</tt> context. The <tt>ctx</tt> object can then be used to actually render to the canvas. The example simply fills two rectangles, by setting fillStyle to two different colors using CSS color specifications and calling <tt>fillRect</tt>. The second fillStyle uses <tt>rgba()</tt> to specify an alpha value along with the color.

The <tt>fillRect</tt>, <tt>strokeRect</tt>, and <tt>clearRect</tt> calls render a filled, outlined, or clear rectangle. To render more complex shapes, paths are used.

Using Paths

The <tt>beginPath</tt> function starts a new path, and <tt>moveTo</tt>, <tt>lineTo</tt>, <tt>arcTo</tt>, <tt>arc</tt>, and similar methods are used to add segments to the path. The path can be closed using <tt>closePath</tt>. Once you have a path is created, you can use <tt>fill</tt> or <tt>stroke</tt> to render the path to the canvas.

Example 2.

<html>
 <head>
  <script type="application/x-javascript">
function draw() {
  var canvas = document.getElementById("canvas");
  var ctx = canvas.getContext("2d");

  ctx.fillStyle = "red";

  ctx.beginPath();
  ctx.moveTo(30, 30);
  ctx.lineTo(150, 150);
  ctx.quadraticCurveTo(60, 70, 70, 150);
  ctx.lineTo(30, 30);
  ctx.fill();
}
   </script>
 </head>
 <body onload="draw()">
   <canvas id="canvas" width="300" height="300">
 </body>
</html>

Calling <tt>fill()</tt> or <tt>stroke()</tt> causes the current path to be used. To be filled or stroked again, the path must be recreated.

Graphics State

Attributes of the context such as <tt>fillStyle</tt>, <tt>strokeStyle</tt>, <tt>lineWidth</tt>, and <tt>lineJoin</tt> are part of the current graphics state. The context provides two methods, <tt>save()</tt> and <tt>restore()</tt>, that can be used to move the current state to and from the state stack.

A More Complicated Example

Here's a little more complicated example, that uses paths, state, and also introduces the current transformation matrix. The context methods 'translate()', 'scale()', and 'rotate()' all apply their operations to the current transformation matrix, which is applied to all rendered points.

<html>
 <head>
  <script type="application/x-javascript">
function drawBowtie(ctx, fillStyle) {

  ctx.fillStyle = "rgba(200,200,200,0.3)";
  ctx.fillRect(5, 5, 60, 60);

  ctx.fillStyle = fillStyle;
  ctx.globalAlpha = 1.0;
  ctx.beginPath();
  ctx.moveTo(10, 10);
  ctx.lineTo(10, 60);
  ctx.lineTo(60, 10);
  ctx.lineTo(60, 60);
  ctx.closePath();
  ctx.fill();
}

function draw() {
  var canvas = document.getElementById("canvas");
  var ctx = canvas.getContext("2d");

  ctx.save();
  ctx.translate(10, 10);
  drawBowtie(ctx, "red");
  ctx.restore();

  ctx.save();
  ctx.translate(80, 10);
  drawBowtie(ctx, "green");
  ctx.restore();

  ctx.save();
  ctx.translate(10, 80);
  drawBowtie(ctx, "blue");
  ctx.restore();

  ctx.save();
  ctx.translate(80, 80);
  drawBowtie(ctx, "yellow");
  ctx.restore();
}
   </script>
 </head>
 <body onload="draw()">
   <canvas id="canvas" width="300" height="300">
 </body>
</html>

Revision Source

<h3 name="Introduction"> Introduction </h3>
<p>With the Firefox 1.1 Developer Preview Release, Firefox includes a new
HTML element for programmable graphics.  <tt>&lt;canvas&gt;</tt> is based on
[<a class="external" href="http://www.whatwg.org/specs/web-apps/current-work/#graphics|the">WhatWG canvas specification</a>],
which itself is based on Apple's <tt>&lt;canvas&gt;</tt> implemented in
Safari.  It can be used for rendering graphs, UI elements, and other
custom graphics on the client.
</p><p><tt>&lt;canvas&gt;</tt> creates a fixed size drawing surface that exposes
one or more <i>rendering contexts</i>.  We'll focus on the 2D rendering
context (incidentally, the only currently defined rendering context).
In the future, other contexsts may provide different types of
rendering; for example, a 3D context based on OpenGL ES.
</p>
<h3 name="The_2D_Rendering_Context"> The 2D Rendering Context </h3>
<h4 name="A_Simple_Example"> A Simple Example </h4>
<p>To start off, here's a simple example that draws two intersecting
rectangles, one of which has alpha transparency:
</p><p><img align="right" alt="Example 1." src="File:en/Media_Gallery/Canvas_ex1.png">
</p>
<pre class="eval">&lt;html&gt;
 &lt;head&gt;
  &lt;script type="application/x-javascript"&gt;
function onload() {
 var canvas = document.getElementById("canvas");
 var ctx = canvas.getContext("2d");

 ctx.fillStyle = "rgb(200,0,0)";
 /* fillRect 
 ctx.fillRect (10, 10, 50, 50);

 ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
 ctx.fillRect (30, 30, 50, 50);
}
  &lt;/script&gt;
 &lt;/head&gt;
 &lt;body onload="onload()"&gt;
   &lt;canvas id="canvas" width="300" height="300"&gt;
 &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>The <tt>draw</tt> function gets the <tt>canvas</tt> element, then
obtains the <tt>2d</tt> context.  The <tt>ctx</tt> object can then be
used to actually render to the canvas.  The example simply fills two
rectangles, by setting fillStyle to two different colors using CSS
color specifications and calling <tt>fillRect</tt>.  The second
fillStyle uses <tt>rgba()</tt> to specify an alpha value along with
the color.
</p><p>The <tt>fillRect</tt>, <tt>strokeRect</tt>, and <tt>clearRect</tt> calls
render a filled, outlined, or clear rectangle.  To render more complex
shapes, paths are used.
</p>
<h4 name="Using_Paths"> Using Paths </h4>
<p>The <tt>beginPath</tt> function starts a new path, and
<tt>moveTo</tt>, <tt>lineTo</tt>, <tt>arcTo</tt>, <tt>arc</tt>, and
similar methods are used to add segments to the path.  The path can be
closed using <tt>closePath</tt>.  Once you have a path is created, you
can use <tt>fill</tt> or <tt>stroke</tt> to render the path
to the canvas.
</p><p><img align="right" alt="Example 2." src="File:en/Media_Gallery/Canvas_ex2.png">
</p>
<pre class="eval">&lt;html&gt;
 &lt;head&gt;
  &lt;script type="application/x-javascript"&gt;
function draw() {
  var canvas = document.getElementById("canvas");
  var ctx = canvas.getContext("2d");

  ctx.fillStyle = "red";

  ctx.beginPath();
  ctx.moveTo(30, 30);
  ctx.lineTo(150, 150);
  ctx.quadraticCurveTo(60, 70, 70, 150);
  ctx.lineTo(30, 30);
  ctx.fill();
}
   &lt;/script&gt;
 &lt;/head&gt;
 &lt;body onload="draw()"&gt;
   &lt;canvas id="canvas" width="300" height="300"&gt;
 &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Calling <tt>fill()</tt> or <tt>stroke()</tt> causes the current path
to be used.  To be filled or stroked again, the path must be recreated.
</p>
<h4 name="Graphics_State"> Graphics State </h4>
<p>Attributes of the context such as <tt>fillStyle</tt>,
<tt>strokeStyle</tt>, <tt>lineWidth</tt>, and <tt>lineJoin</tt> are
part of the current <i>graphics state</i>.  The context provides two
methods, <tt>save()</tt> and <tt>restore()</tt>, that can be used to
move the current state to and from the state stack.
</p>
<h4 name="A_More_Complicated_Example"> A More Complicated Example </h4>
<p>Here's a little more complicated example, that uses paths, state, and
also introduces the current transformation matrix.  The context
methods 'translate()', 'scale()', and 'rotate()' all apply their
operations to the current transformation matrix, which is applied to
all rendered points.
</p>
<pre class="eval">&lt;html&gt;
 &lt;head&gt;
  &lt;script type="application/x-javascript"&gt;
function drawBowtie(ctx, fillStyle) {

  ctx.fillStyle = "rgba(200,200,200,0.3)";
  ctx.fillRect(5, 5, 60, 60);

  ctx.fillStyle = fillStyle;
  ctx.globalAlpha = 1.0;
  ctx.beginPath();
  ctx.moveTo(10, 10);
  ctx.lineTo(10, 60);
  ctx.lineTo(60, 10);
  ctx.lineTo(60, 60);
  ctx.closePath();
  ctx.fill();
}

function draw() {
  var canvas = document.getElementById("canvas");
  var ctx = canvas.getContext("2d");

  ctx.save();
  ctx.translate(10, 10);
  drawBowtie(ctx, "red");
  ctx.restore();

  ctx.save();
  ctx.translate(80, 10);
  drawBowtie(ctx, "green");
  ctx.restore();

  ctx.save();
  ctx.translate(10, 80);
  drawBowtie(ctx, "blue");
  ctx.restore();

  ctx.save();
  ctx.translate(80, 80);
  drawBowtie(ctx, "yellow");
  ctx.restore();
}
   &lt;/script&gt;
 &lt;/head&gt;
 &lt;body onload="draw()"&gt;
   &lt;canvas id="canvas" width="300" height="300"&gt;
 &lt;/body&gt;
&lt;/html&gt;
</pre>
Revert to this revision