Tutorial SVG animations: the basics

SVG basic animations

Until now we have been using SVG to draw static images. However, SVG can also be used for creating dynamic elements like interactivities and animations. In fact, since its early stages of development, beginning in 1997, SVG was even meant to be used for dynamic purposes. There are four methods in which we can create dynamic elements using SVG. These methods are:

  1. declarative animation. (SMIL)
  2. CSS
  3. scripting
  4. using a javascript library, for example the Raphael JS library (for animations) or the D3.js library (for data visualisation)

Of each of the three methods we will give a simple, but characteristic example of a oscilating circle:

Example 1. Declarative animation (SMIL)

SMIL (Synchronized Multimedia Integration Language) is a a W3C standard that is being developped since 1997. The principle behind declarative animation is that the developer describes what should be rendered on the screen (e.g. circle animation), after which the details of implementation are transferred to the client software, SMIL, in our case.

Lets begin with a simple example to show some of the programming priciples of SMIL

<svg width="150px" height="150px" 
viewbox="0 0 150 150" >
<ellipse id="smil1" cx="75" cy="75" 
rx="20" ry="25" fill="#f16529">

    <animate attributeName="rx" 
    dur="5s" 
    values="20;70;20" 
    repeatCount="indefinite"/>
    
    <animate attributeName="ry" 
    dur="5s" 
    values="25;60;25" 
    repeatCount="indefinite"/>

</ellipse>
</svg>

Example 2. CSS

To create an SVG animation with CSS, we can use the CSS keyframe-animation. For the sake of brevity we omit the vendor-prefixes here.

<svg>
  <style type="text/css">
  @keyframes oscilate { 

  0% { 
  transform: scale(1,1);
  }
  
  50% {
  transform: scale(4,3) 
  translateX(-40px) 
  translateY(-50px);
  }
  
  100% { 
  transform: scale(1,1);
  }
}
  ellipse#bubble2 { 
  animation: oscilate 4s linear infinite;
}
  </style>
  <ellipse id="bubble2" cx="80" cy="100" 
  rx="30" ry="40" 
  fill="#f16529">
  </ellipse>
</svg>

Example 3. Scripting

The example1 in which we demonstrated a SMIL animation seemed to be rather easy to follow. In general: animating with SMIL, following a declarative model, is not all that difficult. Scripting (e.g. using javascript) however requires more skills and expertise but is also much more powerful. Here are few things we can do using scripts and cannot do with SMIL:

  • reacting on mouse events, and create eventlisteners
  • build objects with random values for their attributes
  • allow objects to have their attributes modified (nontrivially) by users;
  • allow moving objects to have their directions or velocities adjusted (nontrivially) by the user;
  • detect the distance between moving objects on the screen
Click me
<svg >
<script>
<![CDATA[
function Thanx(){
alert("Thanx man");
}
]]>
</script>
<g onclick="Thanx()" >
  
    <rect id="Rect" x="10" y="40" 
    height="40" width="100" 
    fill="red" rx="10"/>
    
    <text id="Text" x="25" y="65" 
    font-size="20" fill="white">Click me</text>

</g>
</svg>

Be aware of the following aspect of this code:

  • JavaScript embedded in SVG typically resides within a <script> tag. Because SVG is actually XML, you must use: <script><![CDATA[ to begin a script tag and write: ]]></script> to end the script tag. You define JavaScript functions and variables inside that script tag.

Example 4a. The Raphaël JS library

Raphaël JS is a lightweight, open source, JavaScript library that uses SVG and VML to draw vector graphics in the browser. It provides a number of convenient methods for path drawing, vector transformations, interactivity via the DOM and path animation, and supports bitmap image embedding and text drawing. The library greatly simplifies drawing through these methods, acting as an adapter to the underlying (SVG and VML) specifications. if your want to use vector images or animations that must run in all browsers, including IE6 – IE8, using Raphael.js is an excellent choise because it will automatically handle the SVG and VML renderers for you.

<div id="myStage"></div>

<script src="/js/raphael-min.js"></script>

<script>
  var paper = Raphael('myStage', 150, 150);
  var circle1 = paper.circle(75, 75, 50).attr({fill: 'red'}); 
  var text1 = paper.text(75, 75, 'Click me!');
  text1.attr({
  'font-size': 20,
  'fill':'white',
  'font-family': 'sans-serif'
  });

  circle1.click(function() {
      circle1.animate({
      cx: 75,
      r: 0
      }, 1000);
      text1.attr({
      'text-anchor': 'start',
      'font-size': 0,
      'rx':70,
      'font-family': 'arial'
      });
  });
</script>

Example 4b. The D3.js library

D3 refers to Data-Driven Documents. D3 is a JavaScript library that shares many similarities with the well known jQuery library in that it allows direct inspection and manipulation of the DOM. The D3.js library however is intended solely for data visualization, like drawing interactive graphs, althought it can also be used only for creating and animating SVG elements. Let's look at a basic example of coding with the D3.js library. In a following tutorial we will see how we can draw graphs with this library

<script src="http://d3js.org/d3.v3.js"></script>
 
<div id="circle"></div>

<script type="text/javascript">

  var svg = d3.select("#circle")
  .append("svg")
  .attr('width', 150)
  .attr('height', 150);
  svg.append('circle')
  .style('stroke', 'black')
  .style('fill', 'red')
  .attr('id','firstCircle')
  .attr('r', 40)
  .attr('cx', 75)
  .attr('cy', 75);
  
  var positionLabel = svg.append("text")
  .text('Click me!')
  .attr("x", 42)
  .attr("y", 80)
  .attr("font-family", "sans-serif")
  .attr("font-size", "16px")
  .attr("fill", "white");

svg.on("click", function () { 
  d3.select("#firstCircle").remove();
  svg.append('circle')
  .style('stroke', 'black')
  .style('fill', 'red')
  .attr('r', 40)
  .attr('cx', 75)
  .attr('cy', 75)
  .attr('id','secondCircle')
  .transition()
  .delay(0)
  .duration(1000)
  .attr("r", 0)
  .attr("cx", 75)
  .style('stroke', 'black')
  .style("fill", "red");
});

</script>

Leave a comment