Log in

No account? Create an account

SWF-based Canvas

« previous entry | next entry »
Dec. 1st, 2005 | 09:05 pm

After doing some research on this topic, I've come to the conclusion that it's certainly possible to create a generic SWF file capable of running HTML Canvas instructions in Flash. Since it's easier said than done, I'm going to explain how to go about implementing it instead of actually doing it myself.

The first thing to do is to create a simple SWF file containing an implementation of the HTMLCanvasElement and CanvasRenderingContext2D interfaces. All properties and methods should be exposed using Flash 8's ExternalInterface API.

Here's a sample implementation of the fillRect method:

public function fillRect(x:Number, y:Number,
  w:Number, h:Number):Void
  moveTo(x, y);
  lineTo(x + w, y);
  lineTo(x + w, y + h);
  lineTo(x, y + h);
  lineTo(x, y);

I would start by implementing some of the frequently used methods with the clear objective of getting some of the basic samples working.

Once a basic implementation is ready, the next step is to try to use it from within a web page. I'd use Geoff Stearns's Flash detection technique to replace an existing Canvas element with Flash content at runtime.

<div id="content">
  <canvas id="canvas" width="300" height="300"></canvas>
  <script type="text/javascript">
    var fo = new FlashObject("canvas.swf", "canvas",
      "300", "300", "8");

In the above example, "canvas.swf" is the name of the SWF file containing the HTML Canvas implementation. The last argument to the FlashObject constructor is the Flash version number to check for. On systems with no Flash Player 8 installed (all Linux and FreeBSD systems as of this writing), the script will fall back to native Canvas support.

That's really it. The following JavaScript code should produce identical output on both native and SWF-based Canvas implementations.

var canvas = document.getElementById("canvas");

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

ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
ctx.fillRect (30, 30, 50, 50);

Expected output