node package manager

canvas-designer

Canvas Designer / API Referencee

YouTube video: https://www.youtube.com/watch?v=pvAj5l_v3cM

npm downloads Build Status: Linux

"Collaborative" Canvas Designer i.e. Canvas-Drawing tool allows you draw bezier/quadratic curves, rectangles, circles and lines. You can also set strokes, back/forth colors and much more. You can draw using pencils, erase drawing, type texts etc. You can easily add your own tools.

You can check all releases here:

The specialty of this drawing-tool is that, it generates Canvas2D code for you; so simply draw and get the code! That code can be used in any javascript Canvas2D application.

You can submit issues here:

Also, you can collaborate your drawing with up to 15 users; and everything is synced from all users. So, if you draw a line and your friend-A draws quadratic curve and friend-B draws rectangle then everything will be synced among all users!

Youtube Videos

Gif images:

Built-in tools

You can use designer.setSelected or designer.setTools for below tools.

  1. line --- to draw straight lines
  2. pencil --- to write/draw shapes
  3. dragSingle --- to drag/ove and especially resize last selected shape
  4. dragMultiple --- to drag/move all shapes
  5. eraser --- to erase/clear specific portion of shapes
  6. rectangle --- to draw rectangles
  7. arc --- to draw circles
  8. bezier --- to draw bezier curves
  9. quadratic --- to draw quadratic curves
  10. text --- to write texts on single or multiple lines, select font families/sizes and more
  11. image --- add external images
  12. arrow --- draw arrow lines
  13. marker --- draw markers

The correct name for dragSingle should be: drag-move-resize last-selected-shape.

The correct name for dragMultiple should be: drag-move all-shapes.

Upcoming tools

  1. Allow users to add video-streams or screen-streams or existing-webm-mp4-videos
  2. Resize all shapes at once (currently you can resize last selected shape only)

Features

  1. Draw single or multiple shapes of any kind (according to toolbox)

  2. Drag/resize/adjust all the shapes in any possible direction

  3. Rectangles and images can be resized in 4-directions

    Red transparent small circles helps you understand how to resize.

  4. Undo drawings using ctrl+z keys (undo all shapes, undo last 10 or specific shapes, undo range of shapes or undo last shape)

  5. Drag/move single or all the shapes without affecting any single coordinate

More importantly, you can use unlimited designers on a single page. Each will have its own surface and its own tools.

Chinese, Arabic, other languages

You can install following chrome extension for multi-language input tools:

Now type your own language text in any <input> box or anywhere, and simply copy that text.

Now click T tool icon from the tool-box and press ctrl+v to paste your own language's text.

To repeat it:

  1. Type your own language texts anywhere and make sure to copy to clipboard using ctrl+v
  2. Then click T icon, and then press ctrl+v to paste your copied text

You can paste any text: English, Arabic, Chinese etc.

How to Use

  1. Download/link canvas-designer-widget.js from this github repository.

  2. Set designer.widgetHtmlURL and designer.widgetJsURL in your HTML file.

  3. Use this command to append widget in your HTML page:

    var designer = new CanvasDesigner();

    designer.appendTo(document.body);

<!-- 1st step -->
<script src="https://cdn.webrtc-experiment.com/Canvas-Designer/canvas-designer-widget.js"></script>
 
<!-- 2nd step -->
<script>
var designer = new CanvasDesigner();
 
// both links are mandatory
// widget.html will internally use widget.js
designer.widgetHtmlURL = 'https://cdn.webrtc-experiment.com/Canvas-Designer/widget.html'; // you can place this file anywhere
designer.widgetJsURL = 'https://cdn.webrtc-experiment.com/Canvas-Designer/widget.js';     // you can place this file anywhere
</script> 
 
<!-- 3rd i.e. last step -->
<script>
// <iframe> will be appended to "document.body"
designer.appendTo(document.body || document.documentElement);
</script> 

You can even download TAR:

mkdir Canvas-Designer && cd Canvas-Designer
wget http://dl.webrtc-experiment.com/canvas-designer.tar.gz
tar -zxvf canvas-designer.tar.gz
ls -a

Complete Usage

var designer = new CanvasDesigner();
 
websocket.onmessage = function(event) {
    designer.syncData( JSON.parse(event.data) );
};
 
designer.addSyncListener(function(data) {
    websocket.send(JSON.stringify(data));
});
 
designer.setSelected('pencil');
 
designer.setTools({
    pencil: true,
    text: true
});
 
designer.appendTo(document.documentElement);

It is having designer.destroy() method as well.

Use WebRTC!

webrtc.onmessage = function(event) {
    designer.syncData( event.data );
};
 
designer.addSyncListener(function(data) {
    webrtc.send(data);
});

Use Socket.io

socket.on('message', function(data) {
    designer.syncData( data );
});
 
designer.addSyncListener(function(data) {
    socket.emit('message', data);
});

API Reference

widgetHtmlURL

You can place widget.html file anywhere on your site.

designer.widgetHtmlURL = '/html-files/widget.html';

By default widget.html is placed in the same directory of index.html.

// here is default value 
designer.widgetHtmlURL = 'widget.html';

Remember, widget.html is loaded using <iframe>.

widgetJsURL

Note: This file is internally used by widget.html.

You can place widget.html file anywhere on your site.

designer.widgetJsURL = '/js-files/widget.min.js';

By default widget.min.js is placed in the same directory of index.html.

// here is default value 
designer.widgetJsURL = 'widget.min.js';

Remember, widget.js is loaded using <iframe>.

syncData

Pass array-of-points that are shared by remote users using socket.io or websockets or XMPP or WebRTC.

designer.syncData(arrayOfPoints);

addSyncListener

This callback is invoked as soon as something new is drawn. An array-of-points is passed over this function. That array MUST be shared with remote users for collaboration.

designer.addSyncListener(function(data) {
    designer.send(JSON.stringify(data));
});

setSelected

This method allows you select specific tools.

designer.setSelected('rectangle');

setTools

This method allows you choose between tools that should be displayed in the tools-panel.

designer.setTools({
    line: true,
    arrow: true,
    pencil: true,
    marker: true,
    dragSingle: true,
    dragMultiple: true,
    eraser: true,
    rectangle: true,
    arc: true,
    bezier: true,
    quadratic: true,
    text: true,
    image: true,
    zoom: true
});

appendTo

CanvasDesigner is a widget; that widget should be appended to a DOM object. This method allows you pass <body> or any other HTMLDOMElement.

designer.appendTo(document.body || document.documentElement);

The correct name for appendTo is: append-iframe to target HTML-DOM-element

destroy

If you want to remove the widget from your HTMLDOMElement.

designer.destroy();

iframe

You can access designer iframe as following:

designer.iframe.style.border = '5px solid red';
 
window.open(designer.iframe.src);

designer.iframe will be null/undefined until you call appendTo. So always use this code-block:

if(!designer.iframe) {
    designer.appendTo(document.body);
}
designer.iframe.style.border = '5px solid red';

toDataURL

Get data-URL of your drawings!

designer.toDataURL('image/png', function(dataURL) {
    window.open(dataURL);
});

sync

You can manually sync drawings by invoking designer.sync method:

designer.sync();

Here is a real usecase:

webrtcDataChannel.onopen = function() {
    if(designer.pointsLength > 0) {
        // you seems having data to be synced with new user! 
        designer.sync();
    }
};

pointsLength

Each shape is considered as a point. This value allows you check number of shapes that are already drawn on the canvas-designer.

(function looper() {
    document.getElementById('number-of-shapes').inenrHTML = designer.pointsLength;
    setTimeout(looper, 1000);
})();

Or a real usage:

websocket.onopen = function() {
    if(designer.pointsLength > 0) {
        // you seems having data to be synced with existing users! 
        designer.sync();
    }
};

undo

You can either undo drawings by pressing ctrl+z on windows and command+z on Mac; however you can undo using designer.undo method as well:

designer.undo();   // undo last shape 
designer.undo(-1); // undo last shape 
 
// undo shape from specific index 
designer.undo(0);
 
// undo all shapes 
designer.undo('all');
 
// undo last 10 shapes 
designer.undo({
    numberOfLastShapes: 10
})

designer.pointsLength shows number of shapes; and designer.undo accepts shape-index as well.

Add New Tools

First Step

Open widget.html and add your new tool-icon HTML.

<div id="tool-box" class="tool-box"> <!-- search for this div; and include your HTML inside this div -->
    <canvas id="yourNewToolIcon" width="40" height="40"></canvas> <!-- here is your icon-HTML -->
</div>

Second Step

Open decorator.js and decorate your new HTML icon.

var tools = {
    yourNewToolIcon: true // add this line to make sure index.html can use it 
};

Search for decorateLine method, and append following snippet quickly after that method:

function decorateYourNewToolIcon() {
    var context = getContext('yourNewToolIcon');
 
    context.fillStyle = 'Gray';
    context.font = '9px Verdana';
    context.fillText('New', 16, 12);
 
    bindEvent(context, 'YourNewToolIconSelected');
}
 
if (tools.yourNewToolIcon === true) {
    decorateYourNewToolIcon();
} else document.getElementById('yourNewToolIcon').style.display = 'none';

Third Step

Open common.js and add selection-states for your new tool-icon (i.e. whether your new tool icon is selected or not):

var is = {
    isYourNewToolIconSelected: false, // add this line 
 
    set: function (shape) {
        var cache = this;
 
        cache.isYourNewToolIconSelected = false; // add this line as well. 
 
        // ..... don't modify anything else 
        cache['is' + shape] = true;
    }
};

You merely need to set isYourNewToolIconSelected:true also cache.isYourNewToolIconSelected=false.

Fourth Step

Create new file in the dev directory. Name this file as yourNewToolIcon-handler.js.

This file MUST look like this:

var yourNewToolIconHandler = {
    ismousedown: false,
 
    mousedown: function(e) {
        this.ismousedown = true;
    },
 
    mouseup: function(e) {
        this.ismousedown = false;
    },
 
    mousemove: function(e) {
        if(this.ismousedown) { ... }
    }
};

You can check other *-handler.js from dev directory to get the idea how exactly it works.

Now open Gruntfile.js#L43 and add link to your new file: dev/events-handler.js.

Now compile all your changes using grunt.

Fifth Step

Open events-handler.js and make sure that your above yourNewToolIconHandler object is called for mouse up/down/move events.

addEvent(canvas, isTouch ? 'touchstart' : 'mousedown', function (e) {
 
    // you merely need to add this line at the end of this method 
    else if (is.isYourNewToolIconSelected) yourNewToolIconHandler.mousedown(e);
});
 
addEvent(document, isTouch ? 'touchend' : 'mouseup', function (e) {
 
    // you merely need to add this line at the end of this method 
    else if (is.isYourNewToolIconSelected) yourNewToolIconHandler.mouseup(e);
});
 
addEvent(canvas, isTouch ? 'touchmove' : 'mousemove', function (e) {
 
    // you merely need to add this line at the end of this method 
    else if (is.isYourNewToolIconSelected) yourNewToolIconHandler.mousemove(e);
});

First of all, we are checking whether your tool-icon is selected or not: is.isYourNewToolIconSelected

Then we are calling yourNewToolIconHandler dot mousedown/mouseup/mousemove events respectively.

Sixth Step

Open draw-helper.js. Make sure that your new tool-icon can be drawn on the <canvas> surface.

yourNewToolIcon: function(context, point, options) {
    context.beginPath();
    context.moveTo(point[0], point[1]);
    context.whateverYouWantToDoHere(point[2], point[3]);
 
    this.handleOptions(context, options);
}

Usually point[0] is x coordinates; point[1] is y coordinates; point[2] is width and point[3] is height.

Different shapes can handle these points differently.

There is NO-limit for point[index]. You can add as many points as you want.

Complex shapes can add 10 or 20 points.

Seventh Step

Open drag-helper.js and make sure that your new shape can be dragged/resized/move.

Search for p[0] === 'line' and add similar code-blocks for your shape (new-tool-icon) as well.

Eighth Step

Open common.js and make sure that your new shape (tool-icon) is printed on the <textarea> as well.

This allows end-users to copy your shape's code and use anywhere on their own web-pages.

Open common.js file; there is a function updateTextArea inside the "common" object – which is aimed to output into textarea element.

You don't have to change updateTextArea. For simplicity purpose, code is separated in different functions/properties that you've to edit:

  1. forLoop
  2. absoluteNOTShortened
  3. relativeShortened
  4. relativeNOTShortened

Search for p[0] === 'line' and add similar code-blocks for your shape (new-tool-icon) as well.

For more information

Shortcut Keys

ctrl+t (to display text-fonts box)
ctrl+z (to undo last-single shape)
ctrl+a (to select all shapes)
ctrl+c (copy last-selected shape)
ctrl+v (paste last-copied shape)

ctrl+mousedown allows you quickly copy/paste all shapes. (i.e. ctrl button + mouse down)

Contributors

  1. Muaz Khan
  2. Oleg Aliullov

Please make pull-request to update this list.

License

Canvas Designer is released under MIT licence . Copyright (c) Muaz Khan.