Working with Canvas and AngularJS

Kapil Kaushik picture Kapil Kaushik · Nov 7, 2013 · Viewed 44k times · Source

I am taking up a task to re-write the following flash app in HTML5:

http://www.docircuits.com/circuit-editor

Given the complexity of the app and my R&D so far, I have identified AngularJS as the preferred MVC framework for the implementation. The app has various parts such as panels, menus, properties, charts, etc., all of which I believe can be easily implemented in AngularJS.

The key problem, however, is that the component design and interaction (things like, drag/drop, move, wire handling, etc.) need to be Canvas-based, as I have been able to export all the vector graphics from Flash using the CreateJS toolkit (http://www.adobe.com/in/products/flash/flash-to-html5.html) into a Canvas library and not to an SVG.

The problem is that there is no clear way to communicate between the "individual objects inside a canvas" and AngularJS. I have looked at the following examples, but almost all of them work on the canvas object, and not about handling individual components inside Canvas:

AngularJS Binding to WebGL / Canvas

Is there already a canvas drawing directive for AngularJS out there?

I am kind of stuck here, and not sure what to do. Would really appreciate a some comments on:

  • Whether AngularJS is the right choice?

  • Should I try implementing the Canvas part in another library (such as Fabric.js, kinect.js, Easel.js) and integrate it with Angular (which again seems too big a task for now)?

  • If none of the above, what other framework should I switch to that can easily handle canvas as well as other functionality like panels, menus, charts etc. with ease?

Answer

Kapil Kaushik picture Kapil Kaushik · Jan 10, 2014

We finally managed to work with AngularJS and HTML5 Canvas together. Here below, I will share, briefly, our requirements and the approach we followed to achieve it.

The requirement was a bit tricky as we wanted to:

  1. Handle event handles on individual elements inside the canvas, and be able to add these elements dynamically based on the data in AngularJS

  2. Keep data for each individual element in AngularJS while using Canvas for only display of the data.

  3. Use controller inheritance for special handling of data in certain cases (for e.g. all the instances should be movable and draggable, but some instance may need to blink or show some color bands etc.)

To handle the operations on Canvas, we divided it into two parts:

  1. Canvas service

    It does the job of

    • initializing the canvas

    • adding or removing any element from the canvas

    • refreshing the canvas

  2. Instance directive and controller

    • the angular controller keeps the handle for the corresponding "canvas element", and also all the data that is associated with it.

    • the event listeners on each element trigger specific functions in the angular controller which manipulate the instance data

    • the directive watches the instance data in controller, and correspondingly updates the canvas with the help of the canvas service

For controller inheritance, we found the following approach quite useful: https://github.com/exratione/angularjs-controller-inheritance

This helped us create controllers dynamically, and with the help of instance directive, we could also handle individual updates on the canvas along with the generic event handling.

I understand that this approach may not be completely AngularJS-oriented, but it worked well for us, and we were able to handle a reasonable amount of interaction between AngularJS and HTML5 Canvas.