Creating layered animation with SVG. Elements as separate layers

Preparing SVG For use on the web, this is a very simple process, no more complicated than exporting a JPEG or PNG. Use whatever graphics editor you're familiar with (Illustrator, Sketch, Inkscape [free], etc. [or even Photoshop if you're using shape layers]) at the image size you plan to use. I usually work in Illustrator, so I'll explain some of the ways to prepare files in that program, but they generally apply to any program. You might want to convert your text to curves, as the font will most likely render incorrectly, unless you plan to style them with the web font used on the page (which is possible!). It's also not a good idea to convert all objects into single shapes, especially if you have strokes that will need to be manipulated on the page, especially since converting objects often does not reduce file size. Any names assigned to groups or layers will be added to the SVG as an element ID. This is quite convenient for styling, but will increase the overall size file.

Before you export, you need to check that all images are in an integer pixel grid (that is, for example not 23.3px × 86.8px). Otherwise, most likely the image will not have enough clarity and part of the image will be cut off. In Illustrator this can be done as follows: Object > Artboards > Fit to Artwork Bounds. Then click save as and select SVG, and leave the default settings. There's a little optimization we can do here, but it's really not worth it since we'll be using various enhancement techniques later on, so we won't waste time on those tweaks for now.

Tricks for reducing file sizes.

(See optimization)

To achieve smallest size SVG, it would be logical to remove everything unnecessary from it. The most famous and useful program(By at least I think so) for processing SVG it is SVGO . She removes all required code. But! Be careful when using this program if you plan to manipulate SVG with CSS/JS, as it may clean up the code too much, making future changes difficult. Another convenience of SVGO is that it can be included in the process of automatically building a project, but you can also use GUI if you want.

Understanding in more detail with correct removal everything unnecessary, we can do something else in graphic editor. First you need to make sure that you use as few paths/shapes as possible, as well as points on those paths. You can combine and simplify everything that can be simplified, and remove all unnecessary points. Illustrator has the VectorScribe plugin with Smart tool Remove Brush Tool, which will help you remove points and still leave general shape Same.

Preliminary optimization

Smart Remove Brush Tool removed points

Next we will enlarge the image. In Illustrator, it's convenient to turn on View > Pixel Preview with a pixel grid and check how the outlines are positioned. It will take a little time to place the outlines on the grid, but the effort will pay off and result in cleaner rendering (it's best to pay attention to this in advance).

Points off grid

Align to Grid

If there are two or more objects to align, then it is worth removing all unnecessary overlaps. Sometimes, even if the contours are carefully aligned, a thin white line may be visible. To prevent this, you can slightly overlap the objects where they overlap. Important: in SVG, the z-index has a certain order, which depends on the object located below, so it is worth placing the top object in bottom part file in code.

And finally, last but not least, something that is usually forgotten is to enable gzip compression of SVG on your site in the .htaccess file.

AddType image/svg+xml svg svgz AddOutputFilterByType DEFLATE "image/svg+xml" \ "text/css" \ "text/html" \ "text/javascript" ... etc

As an example of how effective this technique is, I'll take the original Breaking Borders logo and optimize it this way: increase the size to what it should be; I’ll put the contours in order; I will delete as many points as possible; move the points by integer pixels; I’ll move all the overlap areas and send it all to SVGO.

Original: 1.413b

After optimization: 409b

As a result, the file size became ~71% smaller (and ~83% smaller when compressed)

One of the best ways presentation graphics online is scalable Vector graphics. This is thanks to the fact that SVG can adapt to any screen size without losing quality.

What is Snap.svg?

Snap.svg is JavaScript library, which aims to help web developers deliver advanced SVG capabilities in Internet. This library is able to load, animate, and even create SVG graphics right in the browser. Snap was created by Dmitry Baranovsky, who also created Raphael, but unlike him, this library made to support most modern browsers.

Creation simple svg graphics

Once you've downloaded the library and included it in your page, the first thing you need to do is create an SVG HTML element:

Then, confirm the Snap library:

Var s = Snap();

By omitting the surface parameters of our drawing, it will automatically be 100% x 100% in size, but if you want to specify a specific width and height, you can do it like this:

Var circle = s.circle(200, 200, 100);

This code creates a simple 100px radius circle that is positioned 200px from the top and left side of our page.

The background of the form fill is black by default, but we can change it, along with the width of the strokes, using the attr method:

Circle.attr(( fill: "#6A8EAB", stroke: "#fff", strokeWidth: 3 ));

Of course, we can create other shapes with using Snap, for example, rectangles:

Var r = s.rect(100, 100, 75, 75, 5);

This code creates a 100px rectangle at the top and left of work area, with a width and height of 75px and a border radius of 5px.

We can also add text:

Var t = s.text(50, 50, "WebDesignMagazine");

You can add things like polygons, ellipses, and gradients. If we have more than one element on the drawing surface, then Snap allows us to group them as follows:

Var circles = s.group(s.circle(100, 150, 70), s.circle(200, 150, 70));

Snap makes it possible to animate our elements:

Circle.animate((r: 50), 2000);

One of Snap's biggest advantages is its ability to load existing SVGs:

Snap.load("image.svg", function (f) ( // Code ));

This code imports the SVG files, but in order to place them on our drawing board we have to add it:

Snap.load("image.svg", function (f) ( g = f.select("g"); s.append(g); ));

Now we have it on the drawing board and we can make it draggable:

G.drag();

And, like the elements we saw earlier, we can also change attributes of our images such as fill color or strokes. But this must be done before the image is added to the board:

F.select("polygon").attr((fill: "#FF0000"));

As you can see, the select method allows us to search through elements. IN in this case, we look for any polygons with a black background and then change them to red.

Are you already using this library in your projects? If yes, leave it in the comments - it will be very interesting to look at the finished version.

High conversions!

We have long promised to make a video about the animation of SVG elements on pages, but somehow it never worked out. Today we are finally pleased to present you the first video in the series, in which we will tell you about SVG animation options: with using CSS, SMIL and JavaScript (using the example of Snap.svg).

In fact, with this video it was like with the Mistrals. There were no circumstances for recording. Well, now it’s finally worked out.

SVG animations

Let's try once again to put everything together with links. There are three ways to animate SVG elements on a page, two of which also apply to HTML elements. I'm, of course, talking about CSS and JavaScript animations. But for SVG you can also use SMIL (Synchronized Multimedia Integration Language) animations.

SMIL animations

This is a very cool technology if we need to animate paths and at the same time store it all in one SVG file. Yes, CSS Animations can also be included in a file, but with their help you cannot animate the d attribute of paths, so SMIL turns out to be much more interesting technology. Actually, JavaScript can also be included directly in SVG files, but browser support is a little different, so you need to think about what and how to use.

SMIL has been supported in all browsers since time immemorial (since earlier versions), except Internet Explorer, which doesn't support these animations until now.

CSS Animations

Everything is very clear here, we have long been accustomed to using CSS for small animations HTML elements. The same can be done with SVG: most attributes can be animated and browser support is much better. Well, because at least Internet Exporer 10 learned about such a phenomenon as CSS animations.

JavaScript animations

The most reliable and convenient solution, as always, is JavaScript, there is no escape from this. When working with interfaces, this is the only option to script something. Fortunately, quite a lot of libraries already exist for working with SVG.

Some even include animation capabilities, such as Snap.svg. I would recommend this library to everyone, although many are accustomed to working with Velocity.js, this approach also has a right to exist.

  • Tutorial

I think many have seen the reviews game consoles new generation from Polygon (Vox Media). These are the ones where the consoles were drawn in blueprint style:

The reviews looked cool, quite unusual and new. About how the main feature of reviews is implemented - SVG animation, how to do something similar yourself, and what other “secret” capabilities the good old SVG hides in terms of animation of the path element - you can find out under the cut.

Stroke-dasharray interpolation, theory

In general, the technique of such line animation is not new, it’s just that until recently SVG and everything connected with it, in my opinion, was unfairly consigned to oblivion, but fortunately the situation is changing. So, the trick to animate the path element is possible thanks to the stroke-dasharray property of the path element. This property allows you to set the parameters of a dotted line, namely the length of the stroke and the space between strokes. If we set the length of the stroke equal to the entire length of the line, we get an ordinary solid line. If you set the stroke length equal to zero, and the length of the gap is again equal to the entire length of the line, then we get an invisible line. And by gradually increasing the length of the stroke with a gap length equal to the length of the entire line, we can simulate its drawing. With this approach, drawing will occur from the beginning of the line. If you suddenly need to draw from the end, then you need to use one more property: stroke-dashoffset . This property specifies the offset for the first stroke. Thus, by decreasing the offset and increasing the length of the stroke, we get drawing from the end of the line.

The guys from Vox Media they used a hybrid option (which, in my opinion, is redundant), by the way, you can (and should) read about how they did this on their blog: Polygon feature design: SVG animations for fun and profit.

Implementation of SVG animation

IN Vox Media they suggest using requestAnimationFrame for smooth animation, but we have slightly different goals, so we will take a simpler route, use the D3.js library and the duration-based animation implemented in it.

Here is the actual working code used to animate the console from the beginning of the article.

Queue() .defer(d3.xml, "PS4.svg", "image/svg+xml") .await(ready); function ready(error, xml) ( //Adding our svg file to HTML document var importedNode = document.importNode(xml.documentElement, true); d3.select("#pathAnimation").node().appendChild(importedNode); var svg = d3.select("svg"), svgWidth = svg.attr("width"), svgHeight = svg.attr("height"); var paths = svg.selectAll("path") .call(transition) ; function transition(path) ( path.transition() .duration(5000) .attrTween("stroke-dasharray", tweenDash) .each("end", function() ( d3.select(this).call(transition) ; )); // infinite loop ) function tweenDash() ( var l = this.getTotalLength(), i = d3.interpolateString("0," + l, l + "," + l); // interpolation of stroke -dasharray attr return function(t) ( return i(t); ) )


Let's start by simply moving along the line, without rotating for now.

Queue() .defer(d3.xml, "wiggle.svg", "image/svg+xml") .await(ready); function ready(error, xml) ( //Adding our svg file to HTML document var importedNode = document.importNode(xml.documentElement, true); d3.select("#pathAnimation").node().appendChild(importedNode); var svg = d3.select("svg"); var path = svg.select("path#wiggle"), startPoint = pathStartPoint(path); var marker = svg.append("circle"); r", 7).attr("transform", "translate(" + startPoint + ")"); transition(); //Get path start point for placing marker function pathStartPoint(path) ( var d = path.attr( "d"), dsplitted = d.split(" "); return dsplitted.split("," ) function transition() ( marker.transition() .duration(7500) .attrTween("transform", translateAlong( path.node())) .each("end", transition);// infinite loop ) function translateAlong(path) ( var l = path.getTotalLength(); return function(i) ( return function(t) ( var p = path.getPointAtLength(t * l); return "translate(" + p.x + "," + p.y + ")";//Move marker ) ) )
Here pathStartPoint(path) pulls the coordinates of the start of the line from the path element's attribute. In translateAlong(path), the coordinates of our marker are set using an interpolator. An example can be seen here: Marker animation along SVG path element with D3.js. You can also combine line drawing animation and marker movement; it might look like this: Marker animation along SVG path element with D3.js II .

Let's complicate the task, add rotation (well, and change the marker from a circle to something more interesting). As a marker we will have a rocket with a width of 48 and a length of 24. Since the marker's default anchor point is the top left corner, we need to offset it so that it snaps to the center of the marker. It is also necessary to take this into account when rotating, because by default it also occurs around the left top corner. We seem to have sorted out the displacement. Now let's move on directly to rotation, here the definition of a tangent will help us, we will determine the angle using the arctangent.

The translateAlong(path) function defining the interpolator will look like this:

Function translateAlong(path) ( var l = path.getTotalLength(); var t0 = 0; return function(i) ( return function(t) ( var p0 = path.getPointAtLength(t0 * l);//previous point var p = path.getPointAtLength(t * l);////current point var angle = Math.atan2(p.y - p0.y, p.x - p0.x) * 180 / Math.PI;//angle for tangent t0 = t ; //Shifting center to center of rocket var centerX = p.x - 24, centerY = p.y - 12; return "translate(" + centerX + "," + centerY + ")rotate(" + angle + " 24" + " 12 "+")"; ) ) )
The implementation can be viewed here.