• Stars
    star
    371
  • Rank 115,103 (Top 3 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 10 years ago
  • Updated almost 4 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Collaborative, extendable, JavaScript Canvas2D drawing tool, supports dozens of builtin tools, as well as generates JavaScript code for 2D animations.

Canvas Designer / API Referencee

Demo: https://www.webrtc-experiment.com/Canvas-Designer/

Advance Demo: demos/dashboard/

Multiple designers demo: https://www.webrtc-experiment.com/Canvas-Designer/multiple.html

YouTube video:

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
  14. lineWidth --- set line width
  15. colorsPicker --- background and foreground colors picker
  16. extraOptions --- extra options eg. lineCap, lineJoin, globalAlpha, globalCompositeOperation etc.
  17. pdf --- to import PDF
  18. code --- to enable/disable code view
  19. undo --- undo recent shapes

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://www.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://www.webrtc-experiment.com/Canvas-Designer/widget.html'; // you can place this file anywhere
designer.widgetJsURL = 'https://www.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>

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);

An example to pass custom data on Canvas-Designer:

var x = 0;
var y = 0;
var width = designer.iframe.clientWidth;
var height = designer.iframe.clientHeight;

var image = 'https://www.webrtc-experiment.com/images/RTCMultiConnection-STUN-TURN-usage.png';

var points = [
    ['image', [image, x, y, width, height, 1], ['2', '#6c96c8', 'rgba(0,0,0,0)', '1', 'source-over', 'round', 'round', '15px "Arial"']]
];

designer.syncData({
    startIndex: 0,
    points: points
});

clearCanvas

Remove and clear all drawings from the canvas:

designer.clearCanvas();

renderStream

Call this method internally to fix video rendering issues.

designer.renderStream();

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,
    pdf: true,
    zoom: true,
    lineWidth: true,
    colorsPicker: true,
    extraOptions: true,
    code: true,
    undo: true
});

icons

You can force/set your own tool-icons:

designer.icons = {
    line: '/icons/line.png',
    arrow: '/icons/arrow.png',
    pencil: '/icons/pencil.png',
    dragSingle: '/icons/dragSingle.png',
    dragMultiple: '/icons/dragMultiple.png',
    eraser: '/icons/eraser.png',
    rectangle: '/icons/rectangle.png',
    arc: '/icons/arc.png',
    bezier: '/icons/bezier.png',
    quadratic: '/icons/quadratic.png',
    text: '/icons/text.png',
    image: '/icons/image.png',
    pdf: '/icons/pdf.png',
    pdf_next: '/icons/pdf-next.png',
    pdf_prev: '/icons/pdf-prev.png',
    marker: '/icons/marker.png',
    zoom: '/icons/zoom.png',
    lineWidth: '/icons/lineWidth.png',
    colorsPicker: '/icons/colorsPicker.png',
    extraOptions: '/icons/extraOptions.png',
    code: '/icons/code.png'
};

You can set like this as well:

designer.icons.line = '/icons/line.png';

Default values are NULL to force icons from /dev/data-dris.js.

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);

// or
designer.appendTo(document.body || document.documentElement, function() {
    alert('iframe load callback');
});

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();
    }
};

captureStream

Get MediaStream object and share in realtime using RTCPeerConnection.addStream API.

<script src="dev/webrtc-handler.js"></script>
<script>
designer.captureStream(function(stream) {
    var url = URL.createObjectURL(stream);
    videoPreview.src = url;

    rtcPeerConnection.addStream(stream);
    rtcPeerConnection.createOffer(success, failure, params);
});
</script>

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
})

// to remove all occurrences of a specific shape
designer.undo('pencil');
designer.undo('arrow');
designer.undo('rect');

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)

Signaling Server

Contributors

  1. Muaz Khan
  2. Oleg Aliullov

Please make pull-request to update this list.

License

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

More Repositories

1

WebRTC-Experiment

WebRTC, WebRTC and WebRTC. Everything here is all about WebRTC!!
JavaScript
11,736
star
2

RecordRTC

RecordRTC is WebRTC JavaScript library for audio/video as well as screen activity recording. It supports Chrome, Firefox, Opera, Android, and Microsoft Edge. Platforms: Linux, Mac and Windows.
JavaScript
6,540
star
3

RTCMultiConnection

RTCMultiConnection is a WebRTC JavaScript library for peer-to-peer applications (screen sharing, audio/video conferencing, file sharing, media streaming etc.)
JavaScript
2,555
star
4

Chrome-Extensions

WebRTC chrome extensions for screen sharing, screen recording, file sharing, youtube+audio sharing, etc.
JavaScript
1,077
star
5

DetectRTC

DetectRTC is a tiny JavaScript library that can be used to detect WebRTC features e.g. system having speakers, microphone or webcam, screen capturing is supported, number of audio/video devices etc. https://www.webrtc-experiment.com/DetectRTC/
JavaScript
663
star
6

WebRTC-Scalable-Broadcast

This module simply initializes socket.io and configures it in a way that single broadcast can be relayed over unlimited users without any bandwidth/CPU usage issues. Everything happens peer-to-peer!
JavaScript
533
star
7

Ffmpeg.js

Ffmpeg.js demos, both for browsers and node.js
JavaScript
487
star
8

MultiStreamsMixer

MultiStreamsMixer is a JavaScript library that allows you pass multiple streams (e.g. screen+camera or multiple-cameras) and get single stream.
JavaScript
431
star
9

RTCMultiConnection-Server

RTCMultiConnection socket.io server (npm install rtcmulticonnection-server)
JavaScript
274
star
10

getStats

getStats is a tiny JavaScript library using WebRTC getStats API to return peer connection stats i.e. bandwidth usage, packets lost, local/remote ip addresses and ports, type of connection etc.
JavaScript
257
star
11

Translator

Translator.js is a JavaScript library built top on Google Speech-Recognition & Translation API to transcript and translate voice and text. It supports many locales and brings globalization in WebRTC! https://www.webrtc-experiment.com/Translator/
HTML
132
star
12

FileBufferReader

FileBufferReader is a JavaScript library reads file and returns chunkified array-buffers. The resulting buffers can be shared using WebRTC data channels or socket.io.
JavaScript
67
star
13

getScreenId

getScreenId | Capture Screen on Any Domain! This script is a hack used to support single chrome extension usage on any HTTPs domain.
HTML
63
star
14

MultiRTC

A skype-like RTCMultiConnection demo application.
JavaScript
62
star
15

DataChannel

DataChannel.js is a JavaScript library useful to write many-to-many i.e. group file/data sharing or text chat applications. Its syntax is easier to use and understand. It highly simplifies complex tasks like any or all user rejection/ejection; direct messages delivery; and more.
JavaScript
58
star
16

Conversation.js

Conversation.js is inspired by skype; and it provides simple events-like API to manage conversations, enable/disable media devices; add/download files; and do anything supported by Skype. It allows you open data conversation between two or more users using their user-ids.
JavaScript
49
star
17

Firefox-Extensions

(discontinued) Firefox extension API are used to enable screen capturing flag for your own domains!
JavaScript
45
star
18

WebSync-Signaling

WebSync is used as signaling gateway with/for WebRTC-Experiments e.g. RTCMultiConnection.js, DataChannel.js, Plugin-free screen sharing, and video conferencing.
JavaScript
42
star
19

ConcatenateBlobs

Simply pass array of blobs. This javascript library will concatenate all blobs in single Blob object.
HTML
39
star
20

WebRTC-ASPNET-MVC

A simple WebRTC one-to-one demo written in September, 2012! It supports public rooms as well as password-protected private rooms! MS-SQL database is used as signaling gateway!
JavaScript
37
star
21

XHR-Signaling

XHR/XMLHttpRequest based WebRTC signaling implementation.
C#
36
star
22

Reliable-Signaler

A reliable socketlio/node.js based signaling implementation for DataChannel.js, RTCMultiConnection.js and WebRTC Experiments.
JavaScript
32
star
23

RTCMultiConnection-SignalR

SignalR project for RTCMultiConnection
JavaScript
21
star
24

Everything

Everything from Muaz Khan β€” HTML5, CSS3, JavaScript, WebRTC, WebGL, Canvas2D, SVG, etc.
JavaScript
19
star
25

Curvature

Curvature is a tool lets you design bezier curves using Canvas 2d APIs!
JavaScript
17
star