Graphics Editor

In this chapter, we will integrate FabricJS with our app and create an HTML canvas-based editor.

Graphics Editor#

Editing graphics on the web requires working with the canvas element. Fabric is a popular canvas library that we are going to use. We'll create an editor component to show at the /graphics/:graphicId route.

By the end of this chapter, we'll have an editor with a canvas and options to add elements like shapes and text:

Editor Wireframe

The big idea is to develop the editor component like a controlled component, for example, an input. This way, we can pass the initial value of the canvas to the editor and add an on-change handler, and keep the editor mostly pure:

Pure Editor Component

Install dependencies#

We'll need the fabric and file-saver package to build our editor:

fabric provides a pragmatic wrapper to HTML5 Canvas and file-saver helps in downloading files, which will be helpful for exporting our graphics.

Editor component#

Fabric works by hijacking an existing canvas node and elevating it to a fabric.Canvas object. This enables Fabric's rich API. It lets us add and remove objects like text, SVG, and images. It also lets us serialize and de-serialize the canvas.

We will create an editor component in app.components.editor.

Set up editor namespace#

Here's the ns setup. We have imported all the required dependencies for the sake of convenience, but feel free to add more as and when you need them:

Accessing fabric classes#

fabric exposes a variety of classes that we'll need to initialize objects. The ES6 syntax for importing with fabric is:

The equivalent CLJS would be:

We also need to ensure that all args passed to fabric are native JS objects and not CLJS data structures - ie be prepared to call clj->js excessively. Data shape is a common source of bugs while dealing with native JS libraries.

Canvas component#

To be able to work with fabric, we need a canvas element in the DOM. Once the canvas element exists, we need to initialize the fabric.Canvas class. We also need to clean up when the canvas is unmounted.

Let's create a canvas component using r/create-class:

  • The canvas component is a class-based component that receives the f-canvas (fabric.Canvas) object, a set-f-canvas and set-selected-object function. We'll talk about set-selected-object later in this chapter. f-canvas and set-f-canvas are equivalent to value and on-change props on an input component. This makes the canvas controlled, as when f-canvas changes, the parent will be notified. This will all make more sense soon!

  • The :display-name property helps with debugging.

  • The :reagent-render method renders a :canvas element with id c.

  • In :component-did-mount method, a fabric.Canvas object is initialized on the canvas with id c. This method is called after the first render, ie the canvas#c will be available in DOM. The initialized canvas is given some default properties like :height and :width. Then the set-f-canvas method is called, indicating to the parent that the controlled component changed state.

  • The call to .on method is a hook into Fabric's event system. We'll cover this shortly.

  • The :component-will-unmount method cleans up the initialized canvas by calling the .dispose method on f-canvas

Background color component#

The canvas will enhance the native HTML5 canvas, but we need more tools to manipulate it. The bg-color tool will present the user with a list of colors to set as the canvas background:

 

This page is a preview of Tinycanva: Clojure for React Developers

Please select a discussion on the left.