Wednesday, 27 November 2013

// // Leave a Comment

Using Snap.svg to create a box that snaps to a grid

I reviewed Snap.svg, the SVG javascript library as my favourite of the current tranche of libraries. This post begins an exploration of how to do simple things in Snap. First we're going to create a square and give it drag behaviour. Then we're going to update the drag behaviour to make it snap to a grid.

Basic Dragging

The first task is to create a square and make it draggable. In Snap, that's very simple:

Working example. The rounded-corner square is made, some attributes are set and then it is made draggable. Very simple.

Snapping to Grid

The next task is to make the box snap to a grid:

Working example.

The drag function is passed two handler functions, the first is called when dragging is happening and the second when drag starts. We use the Snap function snapto to work out the new x and y position of the box. We have to store the original position of the box because it is not passed into the method anywhere.

I do not like having the orig global variable to store the location of the box. I appreciate that this is used temporarily but global scope variables feel dirty. One solution to this is to wrap the whole lot in a function so that the scope of the orig variable would only be in that scope. I would prefer Snap to store the origin and pass it to me.

Dragging with the transform method

SVG elements have a transform attribute that take the original description of the SVG object and transforms it automatically. I needed the original x and y to change, so rejected the transform method. Perhaps this could still be performed with a "drag stop" method that takes the transform and applies it to the original but for simplicity, I will leave it as-is. The transform method looks like this:

Working example. This is the method that is used in the Snap.svg source code.

The problem with drag

I would prefer that drag accepted a context object that had named methods, rather than relying on the order of parameters. Drag would look more like this:

Please note your version! I am writing this in November 2013, the API version is 0.1. There may well be a better way to do this by the time you read this.