HTML5

Reinforcing The HTML5 Canvas With Fabric.js

The past…

Applets

In the previous millennium, HTML markup had limited support for graphics. If we wanted dynamic graphics, or even a page that responded seamlessly to requests, we embedded a JavaScript VM in the page to host an Applet. Indeed, Applets were an original vision for Java. An applet could draw graphics, but there were issues of Java versions vs. browser support across browser releases across vendors.

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.

Image Replacement

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.

Flash

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.

For reasons arguable outside the scope of this article, Adobe Flash declined, while HTML5 blossomed. We can create single page applications using HTML5, Ajax, and JavaScript, but what about those pretty dynamic pictures?

HTML5 Canvas

Today…

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:

  • Animation
  • Interactivity
  • Primitive objects
  • Complex graphic paths
  • Gradient fills
  • Pattern fills
  • Arcs
  • All colors
  • Alpha channel (variable transparency)
  • Multiple canvases per page
  • Stackable canvases
  • Scaling
  • Transformation
  • Rotation
  • 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 Limitations

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.

Wrapper Libraries

Several vendors have filled these needs to varying degrees. We have used each of the following actively-maintained canvas JavaScript libraries:

jCanvas: Leverages jQuery

Zebra: A desktop environment framework on canvas

  • http://www.zebkit.com/
  • Includes many rich UI interactive widgets
  • Ajax and XML-RPC
  • Code an entire client in Zebra
  • JSON interface
  • Drag / drop / resize
  • Events

Fabric.js: Popular; text, drag-drop, resizing – well-supported

  • http://fabricjs.com/
  • 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
  • Events

The fit of each varies with the problem at-hand. Twice, in the past year, we’ve needed drag-drop image capability along with dragged resizing. We wanted to create custom shape classes that could incorporate styled text. Instances of these could extend the canvas API. We evaluated each for use in a couple of projects. In the end, Fabric.js met our requirements. The other two are also excellent.

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.

khs-blog-fabricjs-1
Figure 1 reusable custom image

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.

khs-blog-fabricjs-2
Figure 2 Mockola, Showing a Composed Mobile Phone Wireframe.

Finally

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.

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!

Reference: Reinforcing The HTML5 Canvas With Fabric.js from our WCG partner Keyhole Software at the Keyhole Software blog.

Lou Mauget

Known as Ed Mauget in civilian life. Lou is a name imposed by IBM in 1966. Newly infatuated with Microservices Architecture. Last spring he coded MockOla, a wire-framing tool for Keyhole Software. Have coded in Java since it was conceived. Also worked with C/C++. Current interests include microservices, Docker, Node JS, NoSQL databases, functional programming, single-page web applications … any new software languages/frameworks.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button