Getting Started With Snap.svg
Written by David Conrad   
Thursday, 31 October 2013
Article Index
Getting Started With Snap.svg
Animation

Transformations

Snap.svg makes it very easy to apply transformations to elements or groups of elements. If you want to do really clever things then you need to understand the way the matrix transformations work in homogeneous coordinates - not difficult but not often necessary. 

All transformation are represented by a matrix object which you can create using:

var t=new Snap.Matrix();

You can specify the elements of the matrix you want to create as parameters - a,b,c,d,e,f. If you don't specify parameters you get an identity matrix by default i.e. no transformation. 

To get the transformation you want you need to make use of a set of Matrix methods:

  • add(a,b,c,d,e,f) or add(matrix)
  • clone()
  • invert()
  • rotate(a,x,y)  a is angle, x,y is the rotation center
  • translate(x,y)
  • scale(x,y,cx,cy) x and y are the scale parameters, cx,cy is the center of scaling. If you leave out y it is assumed to be the same as x and cx,cy are zero by default.

There are also some more advanced methods

spilt() breaks a matrix up into translation, scale and rotation - if possible

toTransformString() converts the matrix to an SVG transform string

and x(x,y) and y(x,y) give the x and y coordinates after transforming x,y. 

The basic idea is that you can start with an identity matrix and apply transformations to it to get the overall transformation. 

For example:

var t = new Snap.Matrix();
t.translate(100, 100);
t.rotate(20, 100, 100);

This first creates a new identity matrix, then applies a translation followed by a rotation. Of course you could put the method calls together and use a fluent style of writing:

var t = new Snap.Matrix()
              .translate(100, 100)
              .rotate(20, 100, 100);

 and so on. The result is the same.

How do we apply a transform?

The simple answer is that every graphics element and group supports the transform(matrix) method which applies the matrix before the object is drawn.

So putting this together we can write a simple program that draw some rotated text:

var t = new Snap.Matrix()
t.translate(100, 100);
t.rotate(20, 100, 100);
var text = paper.text(10, 10, "Hello World");
text.attr({"font-size":100});
text.transform(t);

The result is:

transform

 

There are lots of helpful methods that make working with transformations very much easier than with raw SVG but there are also conversion utilities which will convert between SVG transformation strings.

Animation

It is difficult to know what to include or leave out in a first look at something but animation, while it might not be core to all graphics is certainly fun. 

You can animate SVG graphics by directly manipulating their attributes in JavaScript.  For example:

var animate = function(el) {
 var xpos = +el.attr("cx") + 1;
 el.attr({cx: xpos});
};

var circ1 = paper.circle(100, 100, 50);
setInterval("animate(circ1)", 100);
 

Is a crude animation that moves a circle horizontally.

A much better way is to use SNAP's animate method:

Element.animate(attrs,duration,easing, callback);

attrs gives the attributes you want to animate, duration sets the time for the animation and the other two parameters are optional.

Lets start with something very easy. 

var circ1 = paper.circle(100, 100, 50);
circ1.animate({r:100},5000);

This animates a circles radius from what ever value it is to 100 over five seconds. So given the circle starts out with radius 50 it doubles in size to 100.

That's all there is to it.  

You can animate multiple attributes at the same time by specifying them within the attrs object.

For example a circles that moves and grows is:

circ1.animate({r:100,cx:500},5000);

The animated value changes smoothly and linearly from its initial to its final value - this is linear easing. You can set other change functions using the mina object. For example try

circ1.animate({r:100},5000,mina.bounce); 

which causes the circle to animate from a radius of 50 to 100 with a sort of pulsing. You can write your own easing functions just create a function that returns the increment you require at each time step and pass it in place of the mina function. 

Importing SVG

One of the nice things about Snap is that it makes it easy to work with SVG created using drawing packages. You can use any drawing package as long as it can output SVG but InkScape is free, open source and works with Snap particularly well. In particular SVG is its native format. 

Assuming you have InkScape downloaded and installed using it to provide Snap with something to work with is very easy. In this case two rectangle shapes have been placed and colored ready for export:

 

inkscape

 

So that these SVG elements are easy to work with in Snap it makes good sense to give them ids Right click on each star, select object properties and change the ids to read "redRect" and "yellowRect":

 

 properties

 

If you save the drawing you will discover that you have a perfectly standard SVG file but with some additional attributes in the inkscape and sodipodi namespaces - more on these later. 

To load an SVG file all you need to do is. 

var paper = Snap(svgElement); Snap.load("drawing.svg",onDrawingLoaded);

where the first parameter is the URL of the SVG file and the second parameter is a callback function that is run when the file has loaded. The callback is passed a DOM fragment object as its only parameter which contains all of the SVG elements in the file. You can process this fragment and then add it to the paper object when you are ready.

For example:

function onDrawingLoaded(d){
var yellow=d.select("#yellowRect");
paper.append(d);
yellow.animate({width:600,height:600},4000);
}

In this case the yellow rectangle is found using its id and then after it has been added to the paper it is animated in the usual way. 

This just works and you can use the same trick to create complex graphics and work with them in Snap. 

That all there is to it but a few words of warning. If you examine the SVG generated by InkScape you will see polygons and other shapes that appear to have properties like cx, xy for the center etc. These are InkScape properties and you can animate them but they will have no effect on what appears on the screen. The reason is that the shape isn't a standard SVG element but a path that gives the shape. To change the path you either have to change the path string or apply a transformation. 

star

For example, if you draw a green star on the same drawing and set its id to "star" you can use a transformation to move it as follows:

var star=d.select("#star");
var t = new Snap.Matrix();
t.translate(-200, -200);
t.rotate(10, 100,200);
star.transform(t);

You could animate rotation by repeatedly applying the transformation, but at the moment Snap animation doesn't extend to transformations.

Where Next?

There are a lot of other features worth exploring - filters, gradient fills, patterns, masks and the use of events to allow the user to interact with graphics. These are documented, but you will need to experiement. 

There is plenty of scope for a second part to this article so if you want more be sure to comment or email me, David.Conrad@i-programmer.info

snapgraphic

More Information

Snap.svg

Related Articles

Adobe Snap.svg JavaScript Library

Getting started with SVG for HTML5

SVG, JavaScript and the DOM


To be informed about new articles on I Programmer, install the I Programmer Toolbar, subscribe to the RSS feed, follow us on, Twitter, FacebookGoogle+ or Linkedin,  or sign up for our weekly newsletter.

espbook

 

Comments




or email your comment to: comments@i-programmer.info

Banner


JavaScript Canvas - Fetch API

Working with lower-level data is very much part of graphics. This extract from Ian Elliot's book on JavaScript Graphics looks at how to use typed arrays to access graphic data.



JavaScript Jems - The Inheritance Tax

JavaScript should not be judged as if it was a poor version of the other popular languages - it isn't a Java or a C++ clone. It does things its own way.  In particular, it doesn't do inheritance  [ ... ]


Other Articles



Last Updated ( Tuesday, 24 December 2013 )