Canvas2D

From TheSoftwareFactory

Jump to: navigation, search
Canvas2D
Canvas2D is a Javascript library wrapping the HTML5 Canvas element. It implements the entire HTML5 specification on all browsers, and even adds extended functionality. An OO API, based on shapes and events builds on top of this. It also includes a DSL to define diagrams and through aliases the user can define his own sub-DSLs.
Author
xtof
Quick Links
Availability
Canvas2D is a Javascript library, around the HTML5 Canvas element. In the near future it will offer a complete implementation of the HTML5 canvas specification across all browsers. Canvas2D also adds some small extensions that will make drawing illustrations easier.

On top of the drawing functions, it ads the concept of shapes and events. Using these one can define interactive compositions of shapes. The API builds on top of the canvas metaphor, introducing books, sheets, lines, rectangles,... But also connectors that automatically connect shapes to one another.

Besides the Javascript API, Canvas2D uses our Abstract Domain Language to implement and provide a DSL for defining shapes, thus opening up the power and fun to non-programmers. Everybody can now include 2D shape-based images in his webpages.

Developers can extend Canvas2D through its extension API. This way new shapes can be introduced, but it also allows the redefinition of the base shapes. Our own UmlCanvas is such an extension and is a nice example of the flexibility offered by the framework.

Last but not least, there is the concept of aliases, which allows the user to define its own DSL and use it to describe its illustrations using its own language.

Read on to find out how ...

Contents

History

It always comes down to a personal itch. This time was no different. A few months ago, we came up with the idea to start a wiki focusing on UML models. The idea was to collect all the design patterns and knowledge we encountered over the years and bring them together in one central place. To achieve this we also needed a way to visualize these patterns, preferably using UML, in a uniform way. We found out that there is not really a common way to present a (UML) diagram on a webpage. All examples of online UML models relied on screenshots taken of diagrams drawn using different CASE tools and uploaded and referenced as images. All images look different. Not only due to the different CASE tools in use, but also due to different diagramming styles of the authors. This was not what we had in mind, so the rendering of the diagrams had to be under our control. That ruled out using author supplied images. Off course we could have users upload XMI and render images server-side. But even chasing that strategy didn't result is many useable solutions.

Then, in december of 2008, I got introduced to the HTML5 Canvas element and suddenly all pieces of the puzzle just fell in place. If we could render UML diagram elements on this canvas, everything could be done client-side using Javascript. This idea later became UmlCanvas. But before that, a new quest began. One for a library to draw shapes on the canvas element. Again, not with much success. So one night, I started fooling around with a canvas tutorial and started drawing some simple boxes. Next up was a little algorithm to layout connectors between those boxes and not much later, the first UML class even appeared on the canvas. The little experiment got out of hand and soon I just had to continue and separate the UML and the canvas interaction code. Canvas2D was born.

With Canvas2D, we solved the rendering issue. But we still needed a way to define the actual content of the diagrams. Case tools export XMI, but that's not something we wanted our future users to enter somewhere in the wiki. The solution was quickly found in another little project we had lying around: ADL. For a while now I'm playing with this small and generic DSL which I call the Abstract Definition Language. ADL allows us to write down structural definitions of e.g. applications, pretty much the way we do it in UML, but in text and with some special support for the domain at hand. Although we mainly use it to textually model applications at a higher level, at its core it's completely generic, so we could reuse it just for "plain" UML. And that's how Canvas2D got its own "Shapes DSL".

Quickstart Guide

You can download distributions (see the Project Information Box at the top) or you can grab the latest sources from our public Git repository:

$ git clone http://git.thesoftwarefactory.be/pub/Canvas2D.git
$ cd Canvas2D
$ make
...

The build process downloads the required libraries and assembles a compressed standalone JavaScript file, including all dependencies, which you can include in your projects.

Just one more thing ...

Before you get all too excited, let's dim the lights a bit and take look at the state Canvas2D is in today: Canvas2D is pretty much beta software. We have merely implemented the tip of the iceberg and things can change overnight. We believe that with our first (0.1) release we have laid out the foundations for most of the things we thought of up to now, but we're not clairvoyant, so we make no promises that we won't break the current API in the (near) future. We will try not to, but until we reach 1.0 YMMV. Keep an eye on our roadmap to track the planned changes. Our blog is also a great resource of behind-the-scenes information.

Now, to turn the spotlight back on ... Canvas2D is already very useable today, as you will see in the examples below and in our examples section when you give it a spin on your own machines.

Ways to use Canvas2D

Canvas2D can basically be used in three ways:

  • As a complete implementation of the HTML5 specification. This part is complete and ready to be used. As browsers continue their effort to implement more functionality, we will continue to use the best solutions, until all browsers get their act together.
  • As a OO JavaScript API, providing shape classes to instantiate new shapes on the sheets of the canvas.
  • Or through a DSL, offering a nicer and less technical interface, one that you could even offer to users of your own software.

For a quick but more complete introduction to the HTML5 Canvas API see the excellent Canvas tutorial by the Mozilla developers. We will use the first example from this tutorial to compare the three different ways Canvas2D can be used.

HTML5 Canvas API

This first example is the how you can deal with the HTML5 Canvas up to now:

var canvas = document.getElementById("myCanvas");
var ctx    = canvas.getContext("2d");

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

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

HTML5 Canvas2D API Wrapper

At the lowest level, Canvas2D provides a complete implementation of the HTML5 Canvas API, ... but it tries to ease out the rough edges that still exist in all browser implementations. Using Canvas2D you should have the same Canvas-experience in all browsers. When used in this manner, Canvas2D is a drop-in solution for existing code:

var manager = new Canvas2D.Manager();  
var canvas  = manager.setupBook("myCanvas");  
var ctx     = canvas.addSheet();  
manager.startAll();

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

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

Above the full-fletched Canvas2D API is presented. Using one manager, multiple canvas instances can be controlled. But often, you just want to activate one canvas:

var ctx = Canvas2D.activate("myCanvas"); 

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

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

Canvas2D API

Canvas2D adds a layer of abstraction and offers an Object-Oriented and Shape-based API to define scenes:

var manager = new Canvas2D.Manager();
var canvas  = manager.setupBook("myCanvas");
var sheet   = canvas.addSheet();

var rect1 = new Canvas2D.Rectangle( { width: 55, height: 50, 
                                      fillColor:"rgb(200,0,0)" } );
var rect2 = new Canvas2D.Rectangle( { width: 55, height: 50, 
                                      fillColor:"rgba(0, 0, 200,0.5)" } );

sheet.at(10, 10).add( rect1 );
sheet.at(30, 30).add( rect2 );

manager.startAll();

When we use some typical Javascript syntax and the shortcut syntax for activating one canvas, we can trim this to :

with( Canvas2D.activate("myCanvas") ) {
  at(10, 10).add( 
    new Canvas2D.Rectangle( { width: 55, height: 50, fillColor:"rgb(200,0,0)" } ) );
  at(30, 30).add( 
    new Canvas2D.Rectangle( { width: 55, height: 50, fillColor:"rgba(0, 0, 200,0.5)" } ) );
}

Canvas2D DSL

On top of the OO Shape-based API, Canvas2D adds another level of abstraction in the form of an ADL-based DSL:

Sheet mySheet {
    [@10, 10] Rectangle rect1 +geo="55x50" +fillColor="rgb(200,0,0)";
    [@30, 30] Rectangle rect2 +geo="55x50" +fillColor="rgba(0, 0, 200,0.5)";
}

Features

The examples above show the flexibility of Canvas2D, from drop-in replacement with a best-of-breed implementation of the entire HTML Canvas Spec, to a shape-oriented object-oriented API and a full-fletched and extensible DSL. But there is more...

Sheet

A sheet is a wrapper around the HTML canvas. As can be seen in the examples above, to use Canvas2D, a sheet has to be defined.

Book

A book is a collection of sheets. It allows to group sheets and in the nearby future controls will be provided to navigate through the sheets it contains. Currently different sheets can only be activated using Javascript, as is presented in some examples displayed above.

Dynamic Sheets

Take a look at the last example and notice the +dynamic modifier. Now, click on one of the rectangles, or even better, start dragging it around. This is native functionality of our Canvas2D: Everything that is drawn on the canvas is a shape and therefore interactive. Our roadmap reveals even more interactive features. In the next release we will add events, enabling custom event handlers for events on shapes.

Mediawiki Extension

If you look at the source of this wiki page, you will notice that we use the DSL interface to Canvas2D and this by simply including it between <canvas2d> tags. These tags are picked up by our Mediawiki Extension and replaced by the appropriate HTML code to introduce a Canvas2D-enabled canvas element.

Extensibility

Canvas2D is designed with extensibility in mind, both for developers and users. For developers, Canvas2D provides an extension API that allows changing every aspect of the canvas and all shapes on it. Users on the other hand can use special features of the shapes DSL to define their own DSL based on the existing shapes.

TabbedCanvas Plug-in

One of the first plug-ins we added was one that added some framing for our canvas. The TabbedCanvas plugin allow you to add three tabs (on top of the diagram itself) to show the console, the source and some promotional information about Canvas2D.

UmlCanvas

UmlCanvas is in fact what started all of this. We wanted to be able to render UML diagrams on webpages, without uploading plain images. We already had the idea to use ADL as a textual UML DSL, so when we encountered the HTML5 Canvas, all pieces of the puzzle fell together. Soon enough we extracted the pure canvas functionality from UmlCanvas, which became of course Canvas2D. Since from the canvas point of view, UML classes and associations are merely new shapes, UmlCanvas is a classic example of a Canvas2D extension.

Aliases

And last but not least, alias support. Canvas2D provides a nice DSL, but sometimes it is still too much bound to the more technical level of the canvas. Still if you could just rename some of the shapes and maybe even lock some of their properties, allowing you to define your own DSL. This is what Canvas2D calls an alias.

Take the following piece of Shapes DSL code:

shape diagram    : sheet;
shape pc         : image +src="workstation.png" +labelPos="bottom";
shape server     : image +src="server.png"      +labelPos="bottom";
shape cloud      : image +src="cloud.png"       +labelPos="bottom";
shape connection : connector;

Now with that set of our own alias-based shapes, we can now define our diagram using:

#include "shapes/network"
diagram myNetwork +dynamic {
  [@ 15,25] pc     myPC        +label="192.168.1.1";
  [@ 98,10] cloud  theInternet +label="The Internet";
  [@227,20] server myServer    +label="87.233.150.116";

  connection myUplink     +myPC-theInternet;
  connection serverUplink +myServer-theInternet;
}

And you have your own network diagramming tool, with your own DSL, without one line of coding:


Coming Soon

  • Toolbar with
    • Sheet navigation
    • Zoom facilities
  • More default shapes
  • Shape definition format
    • With importers for well known shape-based tools (how's that Visio format these days?)

Got an idea on how to extend or improve Canvas2D ? Feel free to send in a patch, or drop us a note at contact (at) thesoftwarefactory (dot) be.


Compatibility

We've tested Canvas2D on the following browsers:

  • Safari 3.2.1 (on Mac OS X)
    • Mobile Safari (on the iPhone)
  • FireFox (3.0.5 on Windows XP, 3.0.8 on Mac OS X)
    • Minefield (aka known as FireFox 3.6 on Windows XP and Mac OS X)
  • Internet Explorer 6.0-7.0-8.0 (on Windows XP)
  • Opera 9.63 (on Mac OS X)
  • Chrome 1.0 (on Windows XP)

If you can successfully see this page with all Canvas2D instances on it on a browser not listed above, drop us note (contact (at) thesoftwarefactory (dot) be). If you encounter any issues on other browsers, send us the error information and we'll try to fix it. Or even better off course ... send in a patch ;-)

We try to maintain a detailed overview of all aspects of the API on our Canvas2D/Status page. There you can find out what is already supported/implemented.

Known Issues

Canvas2D is not a finished product, as we explained above. But besides incomplete there are issues you might run into while using it. We try to list these issues here, so you are aware of possible hurdles.

Internet Explorer

On Internet Explorer things are slow. This is because IE doesn't support the HTML5 Canvas (and probably won't). There are a couple of workarounds providing different results. We devoted a separate page on our wiki for these alternatives at Canvas2D/IE.

Basically, each workaround provides an emulation layer. Emulation means slower, mostly because this emulation layer is 100% written in Javascript. To overcome this overhead, we try to turn off some functions that aren't really needed. One example of this approach is that we don't add our watermark to the canvas when running on IE. This eliminates the need to generate the text, which in fact is a whole lot of small lines. And a whole lot is ... simply too much for poor IE.

Projects using Canvas2D

  • UmlCanvas, of course our own implementation of UML class diagrams on top of Canvas2D

Are you also using Canvas2D on your website? Drop us a note at contact (at) thesoftwarefactory (dot) be and we'll add a link to it.

License & Credits

Canvas2D is licensed under the BSD License. Which basically allows you to use it in whatever way you like, just keep a reference to this origin. Like many open source work, this project stands on the shoulders of giants. The following projects are imported to create the Canvas2D experience:

  • excanvas by Google is a VML implementation of the HTML5 Canvas, emulating it for IE. It's licensed under the Apache License 2.0. It's slow, but it works. Again, it's slow, surely when animating things. So you might consider popping up a decent browser.
  • canvastext : because the standard HTML5 Canvas specification has no text rendering. So Jim Studt wrote a library that renders a publically available font and released it into the public domain.
  • Tabber is a nice tabsheet implementation in JavaScript by Patrick Fitzgerald. It is released under the MIT license.
  • Prototype is a JavaScript library, which abstracts away some of the more cumbersome features of JavaScript. It's licensed under the MIT License.
Personal tools