SVG Part 2 - Dynamic vector graphics
Tags: svg, graphics, animate
Published: 2022-12-11 18:43:51

> This second post focuses on a less known aspect of the SVG standard: it's dynamic capacities!

In the [previous post](https://dev.to/worldlinetech/svg-part-1-open-standard-for-vector-graphics-5587) of this series we discovered that SVG is a XML-based format compatible with DOM and CSS standards. SVG graphic elements can therefore by manipulated by JavaScript code through the DOM and styled with CSS.

After showing how to mix SVG and HTML, this post focuses and how to animate SVG elements, with three different methods: pure SVG instructions, CSS and JavaScript.

## Mixing HTML and SVG

One of the advantages of SVG is that it can be mixed or nested with other XML languages, such as HTML5 or XHTML for example.

It is possible to mix HTML and SVG elements in the same XML document using different namespaces. Even better this allows to interact with SVG objects from JavaScript code included in the HTML page.

```xml
<html xmlns="http://www.w3.org/1999/xhtml" 
 xmlns:svg="http://www.w3.org/2000/svg">
<body>
  <h3>SVG nested in XHTML</h3>
    <svg xmlns="http://www.w3.org/2000/svg" 
     width="300" height="140">
      <circle id="monDessin" 
       cx="70" cy="70" r="40"
       stroke="black" 
       stroke-width="2" 
       fill="red "/>
    </svg>
  <div>Nesting is possible through the use of namespaces</div>
</body>
</html>
```
![SVG in a XHTML document](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/reqa1or1uov34ukaxdps.png)

## Scripting and events

SVG implements the W3C DOM standard and is therefore manipulable via JavaScript in a similar way to X/HTML. Each element and attribute of an SVG document can be dynamically modified.

Furthermore SVG has an event system similar to X/HTML. Classic events like *onload*, *onunload*, *onclick*, *omouseup*, *onmousedown*, *onmouseover*, *onmousemove*, *onmouseout*... are available. But also specific events related to animations: *onbegin*, *onend*, *onrepeat*. 

The following example changes the color of an SVG element when clicked:

```xml
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:svg="http://www.w3.org/2000/svg">
  <body>
    <h3>Click the circle to change its color</h3>
    <svg xmlns="http://www.w3.org/2000/svg" width="300" height="200">
      <circle id="myCircle" 
       cx="70" cy="70" r="40"
       stroke="black" 
       stroke-width="2" 
       fill="red"/>
      <script>         
      <![ CDATA[
        function doClick(e) {
          document.getElementById("myCircle")
                  .setAttribute("fill", "blue");
        }
        document.getElementById("myCircle")
                .onclick = doClick;
        ]]>
      </script>
    </svg>
  </body>
</html>
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lv7ttr10ykuq0z9trig4.png)

If you want to play with this example use Codepen below:

{% codepen https://codepen.io/raphiki/pen/oNyRgZm %}

## SVG Animations

The SVG standard also contains animations by modifying the attribute values of an element (or groups of elements).

SVG uses time-based animations and not frame-based ones as some other technologies. It is therefore necessary to indicate the start and duration of each animation, which can then vary any SVG attribute. Animations can also run in parallel and be triggered by user events.

Several tags are dedicated to animations:
- *animate*: variation of an attribute over time
- *set*: simple modification of an attribute for a specified duration
- *animateColor*: color transition over time
- *animateMotion*: moving the element along a path (cf. *path* tag described above)
- animateTransform: control of the application of SVG transformations on the element (cf. *transform* tag above)

### Example: change x value

```xml
<text x="10" y="10">Change x value</text>
<rect 
 x="10" y="30" 
 width="200" height="100"
 style="fill:#CCCCFF; stroke:#000099">
  <animate 
   attributeName="x" attributeType="XML" 
   begin="0s" dur="5s" 
   from="10" to="150" fill="freeze"/>
</rect>
```
![Animation: change x value](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h7110hlomy1xy6uz5bko.png)

On Codepen:
{% codepen https://codepen.io/raphiki/pen/QWxPdgw %}

### Example: change visibility

```xml
<text x="10" y="10">Change visibility</text>
<rect 
 x="50" y="50" 
 width="200" height="100"
 style="fill:#CCCCFF; stroke:#000099"
 visibility ="hidden">
  <set 
   attributeName="visibility" 
   attributeType="XML"
   begin="2s" dur="3s" 
   to="visible"/>
</rect>
```
![Change visibility](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pq32ybat0xwcykjuiiwp.png)

On Codepen:
{% codepen https://codepen.io/raphiki/pen/jOKoEJa %}

### Example: change color with motion

```xml
<text x="10" y="10">Change color with motion</text>
<rect 
 x="50" y="50" 
 width="200" height="100" 
 style="stroke:#000099">
  <animate 
   attributeName="fill" 
   from ="red" to="blue" 
   dur="4s" fill="freeze"/>
  <animateMotion 
   dur="6s" 
   path="M10 10 L 100 50" 
   rotate="auto"/>
</rect>
```
![Animate color with motion](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iznk4ku9du2dsltflgw9.png)

On Codepen:
{% codepen https://codepen.io/raphiki/pen/BaVeyeW %}

In the previous examples, animations are triggered after a certain number of seconds, specified via the *begin* attribute. It is also possible to associate this trigger with a user event, for example with *begin='mouseover'*.

More complex animations can be achieved by parallelizing simple animations. The animations have many more parameters to control their timeline and sequences, they are not detailed here for the sake of conciseness.

## CSS Animations

SVG elements can be styled by inline or external CSS instructions. This means that they can also be modified with classic CSS [animations](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations) and [transitions](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions).

For instance let's use CSS to ease the change of color of our rectangle when hover:

```xml
<text x="10" y="10">Change color with CSS</text>
<rect id="myRect" 
 x="10" y="30" 
 width="200" height="100"/>
```

```css
#myRect { 
  fill: #CCCCFF; 
  stroke: #000099; 
  transition: fill 2s ease-out;
}
#myRect:hover { 
  fill: #4e86b1; 
}
```

Here is another example using CSS transformations.

```xml
<svg>
  <rect class="top" 
   x="20" y="29" 
   width="60" height="7.85106" 
   fill="#000" />
  <rect class="middle" 
   x="20" y="45.5745" width="60" 
   height="7.85106" 
   fill="#000" />
  <rect class="bottom" 
   x="20" y="62.1489" 
   width="60" height="7.85106" 
   fill="#000" />
</svg>
```

```css
svg {
  cursor: pointer;
}

rect {
  transition: all 0.3s ease-in-out;
}

svg:hover .top {
  transform: rotate(45deg);
  transform-origin: center top;
  x: 50px;
  y: 35px;
}

svg:hover .middle {
  x: 0;
  opacity: 0;
}

svg:hover .bottom {
  transform: rotate(-45deg);
  transform-origin: center top;
  x: -20px;
  y: 25px;
}
```

Result on Codepen:
{% codepen https://codepen.io/raphiki/pen/mdKYxvQ %}

## JavaScript Animations

They are several JavaScript libraries simplifying SVG creation and animation, like for instance [D3.js](https://d3js.org), [Chart.js](https://www.chartjs.org), [Velocity.js](http://velocityjs.org) or [Raphaël](https://dmitrybaranovskiy.github.io/raphael/).

Let's play with [snap.svg](http://snapsvg.io). It is a complete rewrite of Raphaël by its original author, who now work for Adobe (yes the company who created Flash! The circle is complete). 

One interesting feature is the ability to work with existing SVG.

#### Example of dynamic text animated with snap.svg

Declare a empty SVG element in the webpage:
```xml
<svg id="svg" width="100%" height="400" 
 version="1.1" xmlns="http://www.w3.org/2000/svg">
</svg>
```
Import the snap.svg library and use it to create the text animation:

```javascript
var s = Snap("#svg"); 
var text = 'Dynamic text animated with snap.svg';

var textArray = text.split(" ");
var len = textArray.length;
var timing = 750;

for( var index=0; index < len; index++ ) {
  (function() {
    var svgTextElement = s.text(
      350,
      100, 
      textArray[index]
    ).attr(
      { 
        fontSize: '120px', 
        opacity: 0, 
        "text-anchor": "middle" 
      }
    );
    setTimeout( function() {
      Snap.animate( 0, 1, function( value ) {
        svgTextElement.attr(
          { 
            'font-size': value * 100,  
            opacity: value 
          }
        );
      }, timing, mina.bounce, function() { 
        svgTextElement.remove() 
      });
    },index * timing)
  }());
};
```
In Codepen (click on the *Rerun* bottom-right button if you missed the animation):
{% codepen https://codepen.io/raphiki/pen/dyKEYem %}

#### Advanced example of snap.svg mascot animation:
{% codepen https://codepen.io/raphiki/pen/PoavPMr %}

## Animation tools

It is also possible to use specific editors to create SVG animation. They are different from static SVG editors like Inkscape or adobe Illustrator. They usually use all or part of the previous techniques to animate SVG documents.

Here are some examples of such tools:
- [Adobe Animate](https://www.adobe.com/products/animate.html) supports import/export of SVG files and animations
- [SVGator](https://www.svgator.com) is an online tool dedicated to SVG animations
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ozc7s2gj59367f78b7m.png)
- [SVG Artista](https://svgartista.net), an open source online editor, proposes to apply a few CSS animations on an existing SVG document

Static SVG documents are not always optimized when they are created or exported from various editors. The [SVGO](https://github.com/svg/svgo) tool (for SVG Optimizer) is very useful to get rid of useless or redundant information from such SVG files.

## Conclusion

SVG is a powerful language and technology, supported by all recent browsers but is underestimated and not exploited to its full potential. In addition to the lack of support for audio and preload support, its other downside is that it's too often reduced to a static graphic format. 

Let’s hope recent and mainstream animation tools and frameworks will support its dynamic capacities and make Dynamic SVG more visible and adopted.