Search code examples
javascriptcanvasfabricjspaperjs

Creating "Tools" in FabricJS?


I am working on a simple editor where you can move text, pictures, and pretty much anything around. It's nothing too complicated, however I am having an issue choosing between using PaperJS and FabricJS - The main reason being the ability to natively transform items (rotate, scale, etc.).

Even though I love PaperJS, I am really considering moving to FabricJS. I create tools for PaperJS like this:

function shapeTool(options) {
    this.tool = new Tool();
    var options = $.extend({
        shape: "circle",
    }, options);

    this.tool.onMouseUp = function(event) { ... }

    ...
    ...

    this.tool.activate();
    return tool;
}

This is probably the worst way to create them, but for me it's easy to throw all these functions in a file and init my tools: var tool = new shapeTool(options);

Since I will possibly be moving to Fabric, what is the easiest way to make modular tools. In which I can swap between them? (i.e. I have a toolbar and when i click a button my tool changed so i can freedraw, insert images, etc)

Clarification: When I mean a tool, I am talking about a tool in PaperJS. IN Paper, we are able to swap the canvas's active tool. The tool would handle the current mouseDown, KeyDown, etc. events for the canvas. I could write different tools for things like inserting shapes and images, and write one for freedrawing. I could then set the active tool to either one. This would allow me to swap between freedraw and inserting shapes.

Thanks, Hunter M.


Solution

  • In FabricJS you interact with the behaviour of mouse with events.

    Cavas fires:

    • mouse:down
    • mouse:move
    • mouse:up
    • mouse:over
    • mouse:out

    You register events with ON and OFF:

    canvas.on('mouse:down', handler);
    

    You have just on predefined state that is drawingMode true or false

    canvas.isDrawingMode = true;
    

    And free drawing starts.

    When not drawing the mouse down and up or move can be customized by a property you add to canvs.

    canvas.myState = 'addStamps';
    

    Then in your handler:

    handler(e) {
      switch (canvas.myState) {
        case 'deleteItems':
          e.target && canvas.remove(e.target);
        break;
        case 'addStamps':
          canvas.add(new fabric.Image('stamp.jpg'));
        break;
      }
    }
    

    You have to do same for mouse:up or mosue:move if you need interaction other than clicks.

    This is one of the many ways you can obtain a similar effect.