This world is but a canvas to our imagination.
-Henry David Thoreau
Dynamic Web Graphics
A plugin concept addressed the versioning issue, but the downloads for the Applet, the JVM, and even of the plugin updates could be huge. Security issues gave the Java plugin a bad reputation. Applets became rare, except in niche applications that insisted on interactive web-based graphics.
An alternative approach to dynamic graphics always was available: a replaceable embedded static raster graphic image. Here, an img element referenced an image URL, causing a graphic to appear in a rectangular hole on the page. For a dynamic image to morph because of user inputs, the server had to send a replacement image. The advent of silent Ajax / XHR eliminated the distracting page repaint flicker, but this image-replacement approach was cumbersome. It could be network-intensive.
Adobe Flash ushered in attractive rich graphic web pages. It played a movie in a Flash VM HTML plugin, scripted by Adobe ActionScript. There, we could create and dynamically modify images or entire UI repaints as frames of a movie having no flicker. ActionScript enabled true single page applications that behaved like a desktop application framed in a browser. Indeed, Adobe Air targeted the desktop directly.
HTML5 includes a canvas element. An HTML5 canvas is an empty rectangular container on page. It supports a low-level API used by scripting. Create a blank canvas by inserting an HTML canvas element into HTML markup.
<canvas id=”canvas1” width=”500” height=”400”></canvas>
This is boring! Nothing appears unless a script draws something on it. The canvas API uses a context to hold a multitude of settings that compose the drawing state of the canvas.
This paradigm is similar to the context concept in historical graphics engines. We make settings to a context, call a method or two, and then something attractive may appear on the screen. It’s a procedural API. The HTML5 canvas supports drawing text, as well as drawing primitive objects, such as lines, circles, or rectangles. Moreover it enables complex stepwise paths of drawing instructions.
A partial set of canvas capabilities is:
- Primitive objects
- Complex graphic paths
- Gradient fills
- Pattern fills
- All colors
- Alpha channel (variable transparency)
- Multiple canvases per page
- Stackable canvases
- Direct pixel manipulation
- Render an image, movie, or another canvas
- Hit test a point on a path
- Quadratic curve
- Bezier curve
- Region clipping
- Stylized line end caps
- Airbrushed shadow effect
- Mapping to URL
- State save / restore
- Measure text
- Fill text
The canvas API enables impressive graphics. Really! Check this site: http://code.tutsplus.com/articles/21-ridiculously-impressive-html5-canvas-experiments–net-14210 . Click some of those links!
Canvas appears comprehensive. What more do we need?
…Sorry, the canvas API is low-level. Check this yawner at https://html.spec.whatwg.org/multipage/scripting.html#2dcontext. The canvas API is a step-wise procedure for drawing objects. Objects! As in “object-oriented programming?”
What if we want to interact with a graphic object: drag it, rotate it, resize it, or type text into it? Maybe we want to compose several low-level objects into a complex custom object class. It seems that canvas cries out for a simple API for user-interactive behavior. We’d like to instantiate some wrappers for a 2-D location, let them render themselves, and then let an end user manipulate them in some way.
jCanvas: Leverages jQuery
- Maps canvas operations to jQuery selectors
- Layer API for interactivity – a canvas per object
- Drag layers
- Events via jQuery
Zebra: A desktop environment framework on canvas
- Includes many rich UI interactive widgets
- Ajax and XML-RPC
- Code an entire client in Zebra
- JSON interface
- Drag / drop / resize
Fabric.js: Popular; text, drag-drop, resizing – well-supported
- Wraps canvas API in a more-declarative manner
- Object wrappers for primitive widgets
- Compose and group objects
- Create reusable custom object wrappers
- JSON interface
- Shadow API
- Transform and scale
- Drag / drop /resize / rotate
Composing Objects With Fabric.js
In each case, we wanted to create a boilerplate object that we could reuse as if it were built into HTML5 canvas. For example, we wanted a wireframe mobile phone for Mockola, a wireframe authoring tool. We required a custom object that we could instantiate as a program object that rendered a graphic.
We used the low-level canvas context-based path API to create our prototype phone wireframe from arcs, lines, rectangles, and a tiny circle. We wrapped this procedure into a Fabric.js class by using an extension method,
fabric.util.createClass. We would “new” that resulting prototype class, at-will, to add its newborn custom object to the canvas.
Thereafter, it was a simple matter of programming (SMOP), to stamp out any number of phone images on a canvas when the user dragged and dropped its icon representation from a palette. Drag and drop, another HTML5 technology, was our friend.
Figure 1 shows our custom Fabric.js wireframe phone object instantiated on a canvas. Note the Fabric.js-provided drag handles used for resizing. They’re a settable property, as is a rotation handle that we disabled.
Figure 2 shows a development rendition of our wireframe application, Mockola. Here, we’ve dropped other custom objects atop the phone to show a hypothetical mobile application screen.
In this article, we spewed some graphic history, mentioned HTML5 canvas as state-of-art, but then tore it a little, so that we could mend it with a cool object framework.
We didn’t present code nor did we show many pictures – odd, considering the pictorial nature of the subject. Why not pictures? Their number would be insufficient and anticlimactic. Instead, click those links above! There are a huge number of impressive interactive demos, along with code.
For starters, check out our HTML5 Canvas Guitar tuner.
If you’re interested in the HTML5 canvas API without the wrappers, see http://www.w3schools.com/tags/ref_canvas.asp for an accessible high-level reference.
Have fun painting!