News

Use SVG to dynamically draw diagrams

Discover the techniques behind the beautifully-rendered circuit diagrams found on Formula1Data

Screen-shot-2014-09-15-at-17.42.54

Screen shot 2014-09-15 at 17.42.54

DOWNLOAD TUTORIAL FILES

The project assets

To follow this technique, we require two sets of assets. Firstly you’ll need the superb JavaScript library d3.js, by Mike Bostock, which can be downloaded via d3js.org and Github. Secondly, you can also find a Github repository containing our example assets at github.com/doriancami/F1Data-Circuit-SVG-Draw and here we primarily need the ‘circuits’ folder.

Structuring the HTML page

Create a new HTML file, name as desired, in our example index.html, and include the d3.js source code before or after the end <body> tag. If you’ve downloaded the D3 repository you can attach either the d3.js or d3.min.js files locally to your page, or, as we have, link instead to the latest release CDN. After this d3.js script call add a new <script> tag to include our JavaScript workfile named here as f1d-draw.js.

001        </body>
002    <script src=”http://d3js.org/d3.v3.min.js” charset=”utf-8”></script>
003    <script src=”js/f1d-draw.js” charset=”utf-8”></script>
004    </html> 

Add some style

Next we’ll borrow some of Formula1Data’s CSS styling by setting the document’s background colour to black (#1a1a1a) inside the <head> tag. Finally we complete our page by creating a container <div> element with an id of ‘circuit’. This is where our SVG element will be appended by our JavaScript code in the subsequent step. So your HTML page should look like this:

001    <!DOCTYPE html>
002    <html lang=”en”>
003        <head>
004            <meta charset=”UTF-8”>
005            <title>Formula1Data - SVG Drawing Tutorial</title>
006            <style>
007                html {
008                    background-color: #1a1a1a;
009                }      
010            </style>
011        </head>
012        <body>
013                <div id=”circuit”></div>
014        </body>
015        <script src=”http://d3js.org/d3.v3.min.js” charset=”utf-8”></script>
016        <script src=»js/f1d-draw.js» charset=»utf-8»></script>
017    </html>
018    

Random numbers

Next create the JavaScript file named f1d-draw.js, place within a ‘js’ folder in the root of your page and start coding. First we generate a random number between 1 and 5, stored within an ‘nb’ variable, and the container. Now we’re ready to load SVG files randomly with the d3.xml() function, which we’ll add in the following step.

001    var nb = Math.floor((Math.random() * 5) + 1);
002    var container = document.getElementById(«circuit»);

Call D3.xml function

Call this XML function with the random number used to point to each of the five SVG files. Make sure that the paths to the circuits folder is correct here. Then we create an SVG element and append it to our <div> container. Incidentally, to successfully load your SVG with d3.xml, you must place your work files inside your MAMP or XAMPP localhost.

001    d3.xml(‘circuits/circuit’+nb+’.svg’,function(xml){
002        var circuit = xml.documentElement;
003        container.appendChild(circuit);
004    });

Animate SVG element

By now you’ll notice your page merely loads random circuits. To animate, you need to get all of the paths present inside your circuit SVG. We then build a statement for each path with a For loop, first grabbing the path length with the getTotalLength() function. Calling ds.js again we then animate the path dasharray and dashoffset properties to form the drawing effect. Save, load and refresh to preview your first SVG Circuit drawing animation!

001    var paths = circuit.getElementsByTagName(“path”);
002    for(var i = 0; i < paths.length; i++){
003    var length = parseInt(paths[i].getTotalLength());
004        d3.select(paths[i])
005                .style(«stroke-dasharray», length)
006                .style(«stroke-dashoffset», length)
007                .transition()
008                .duration(2000)
009                .ease(‘linear’)
010                .style(«stroke-dashoffset», 0);
011    }});
012    
×