Creating a basic visual editor with svg.js – Part 1

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedIn


Creating a browser based visual editor is not an easy task. The user workflow for editing the graphical elements, rotating them, selecting their colors and shape contains so many alternative paths and features to become easily overwhelming for developers that just want a quick and direct solution to get a project going.

This miniserie will describe our problem, our solution and the issues we had to solve while creating our own online svg editor.

We developed our own editor for and while it is not exceptionally good and it is not a pinnacle in UX it gets the job done. It is quite far from fully featured online svg editors, but delivering our own solution allowed for greater integration of the common use case and streamlined user workflow by a great deal.

The editor, with it's own documentation.
The editor, with it’s own documentation.

We had a limited feature set we wanted to support:

  • adding and removing shapes
  • rearranging shapes
  • adding interaction details to shapes
Editor and live version of an interactive.
Editor and live version of the same interactive.

Manipulating svg images in JavaScript is quite easy, there are plenty of libraries for that. We used svg.js for our editor, and discovered the hard way all the challenges and solutions that such development entails.


The easy part: drawing and interacting

Svg.js gives a very nice set of high level features to build your interactive application. Creating the building blocks for each shape was incredibly easy:


//the gradient used in the rectangle
var g = draw.gradient('linear', function(stop) {, color)//user selectable, grad)//user selectable

//shadow rectangle
var shadow = draw.rect(sizey,sizex).radius(rad).center(x+10,y+10);
//gets filtered by blur to make it more soft
shadow.filter(function(add) {
 add.gaussianBlur(5) //
 this.size('200%','200%').move('-50%', '-50%') //the shape clip need to be extended

//the actual rectangle
var shape = draw.rect(sizey,sizex).radius(rad).center(x,y).fill(g).stroke({width:1, color:'#333'});

//the selection box. this is always present colored transparent,
//when user selects a shape, opacity is changed. much simpler than add/remove the shape
var selection = draw.rect(sizey+26,sizex+26).radius(rad+8).center(x+5,y+5).fill({ color: '#fff', opacity: 0.0 }).stroke({width:0, color:'#f33'});

//makes the selection shape soft edged
shape.filter(function(add) {
 var blur = add.offset(0,0);
 blur =;

 add.blend(add.source, blur)

//big box label
var tshape = draw.text(text).font({
 family: 'Arial, Helvetica, sans-serif',
 size: 30
}).center(x, y).fill(ctext);
Link to JSFiddle


Developing user interaction was as easy:


//enable user to drag the shape around with the mouse

var cb =  function(){
        //this update the edit dialog data 
        //and makes the selection border visible
var dbc = function() {

//register selection and interaction callback


This method of creating interactives is very convenient and leverages the wonderful draggable plugin for svg.js, taking care of all the complexity of the mouse event handling. However it does have its drawback. After a dragging event reconstructing the exact group position has proven difficult, because of the interaction of groups, rotations and transform in the svg model.

Unable to query the position of the shape or the transform from the group to the shape we had to resort using the group bounding box as an indicator of the position of the draggable. It is not as robust and relies on fixed offsets to subtract the shadow from the bounding box to obtain the real centre of the shape, and caused us to rework all of our models to take into account the need of tracking groups as well as shapes.

But that will be discussed in part 2 of this miniserie on svg.js.


Meanwhile, if you want to play with the editor concepts, Concept Maps sources have been made available trough IBM developerWorks

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedIn

Leave a Reply

Your email address will not be published. Required fields are marked *