© Alex Libby  2018
Alex LibbyBeginning SVGhttps://doi.org/10.1007/978-1-4842-3760-1_10

10. Taking It Further

Alex Libby1 
(1)
Rugby, Warwickshire, UK
 

We’re almost at the end of our journey through the world of SVG in the browser – question is, what next? Where can we go from here? Well, that’s easy to answer: over the course of this chapter, we’ll work our way through some more involved examples, to give you, the reader, a flavor of what is possible, and why it is worth making the transition to using SVG within your web projects.

Manipulating SVG with JavaScript

Throughout the course of this book, we’ve made use of a number of libraries to help create and manipulate SVG graphics – after all, if it helps make it easier to create a custom animation effect, or that stunning piece of artwork, when time is against us, then using a library will clearly help save time.

However, what if for some reason this wasn’t possible? If for example you’re working on a code-heavy site where site speed is super critical, we may be forced to go native (so to speak), and edit our SVG content manually.

Thankfully this is easy enough to do using standard JavaScript – it can be quite refreshing to not have to use a library for once! To see how easy it is, I’ve created a very rough and ready demo in CodePen – trust me: it won’t look perfect, but it’s about the process, and not just the final answer.

Manipulating SVG Images Using JavaScript

Let’s make a start on setting up our code, before exploring what each part does in more detail:
  1. 1.

    We’ll begin by extracting a copy of the vanilla folder and save it to our project area.

     
  2. 2.

    Next, go ahead and browse to https://codepen.io , then hit Create | New Pen, and copy the contents of markup.txt file into the HTML pane.

     
  3. 3.

    We need to add a little styling, so let’s add the style rules from styles.txt in the CSS pane of our session.

     
  4. 4.

    Finally, let’s add in the script that provides the magic that makes it all work – copy and paste the contents of script.txt into the JS pane of our CodePen session.

     
  5. 5.

    Go ahead and save your work – you can save it as Anonymous or under your own account, if you have an existing login for CodePen.

     
  6. 6.

    If all is well, we should see something akin to the screenshot shown in Figure 10-1.

     
../images/461821_1_En_10_Chapter/461821_1_En_10_Fig1_HTML.jpg
Figure 10-1

Playing with SVG and JavaScript...

Well, I’m sure you will agree that it is no masterpiece, but don’t say I didn’t warn you! Our demo was all about having a bit of fun, with no expectation that it would be perfect, but more about learning the process involved in creating our shapes. This said, the demo exposed a number of key principles, so let’s explore these in more detail.

Dissecting the Markup Code

If we are not able to make use of a library, then clearly we need to add code to manage functionality otherwise taken care of by the library. One might be forgiven for thinking that we are between a rock and a hard place – what we gain in site speed (from not calling extra resources), we risk losing when adding additional code! Granted, we won’t be adding so much, but it is a risk we still need to manage carefully.

Keeping this in mind, let’s take a look at the code we used in more detail – we will split this into two parts, starting with creating each object used in the demo:

The markup we’ve used is nothing new – we set up an initial <div> to act as our container, inside of which we create an SVG element. We add in a number of shapes – it starts with a standard <rect>, followed by a <circle>, then <text> and <polygon> objects:
<div id="container">
  <svg id="site" xmlns:="http://www.w3.org/2000/svg" height="300" width="500" preserveAspectRatio="xMidYMax meet">
    <rect x="0" y="0" width="100%" height="50" />
    <circle id="btn" cx="80" cy="150" r="20"/>
    <text x="15" y="35" fill="white">This is our SVG</text>
    <polygon id="square" points="100,30 180,30 180,100 100,100" fill="grey" stroke="#000">
      <animate begin="square.click" id="movepoint" begin="indefinite" fill="freeze" attributeName="points" dur="500ms" to="30,30 150,30 100,100 30,100" />
    </polygon>
</svg>This is where things get a little more interesting – we’ve implemented two event handlers: one to animate the polygon object:
  <br>
  <input type="button" value="Click Me" />
… with the second used to change the color of the polygon object defined with an ID of square:
  <input type="button" value="Set fill color" onclick="setFillColor()"/>
</div>
We now come to the crux of our code – the JavaScript used to create and manipulate additional shapes used in our demo. We kick off with setting a number of variables that are used in our code:
// define variables
var svg, svgStar, rotation = 0, a = 0;
var svgns = "http://www.w3.org/2000/svg";
var circleBtn = document.querySelector("#btn");
var svgBox = document.querySelector("#site");
var circleBtn = document.querySelector("#btn");

We then create the first of our additional shapes – a polygon, which will be displayed as a triangle on screen. We’ve used the createElementNS method to construct it, passing in the SVG namespace.

It’s important to note that when creating SVG objects in code, we should use this to construct our shape, when we might otherwise have used createElement.

Why? There is a valid reason for this – using document.createElement is the standard method for creating elements within JavaScript. However, SVG as a format uses namespaces; we can separate common elements or objects that are on the same page but were created using different sources. If we use createElementNS, this simply allows us to group common elements together with a common namespace (or identity tag), so that we can style only those elements that should be styled.

We then set the various points of our shape, before appending it to the main SVG specified in the HTML pane of our demo (under the ID of #site):
// Create SVG polygon shape in code
var polygon = document.createElementNS(svgns, "polygon");
polygon.setAttributeNS(null, "points", "150,10 200,140 110,160");
svg = document.getElementById('site').appendChild(polygon);
polygon.id = "triangle";

It’s worth noting that you can get away with using .setAttribute but ideally should use .setAttributeNS for the same reason. Take a look at the code coming up for the Bezier curve – you will see both formats in use, although the latter is preferable!

Moving on, we can create other objects using similar code – this example is for the star within the demo:
// Create SVG star and fill it in code
var star = document.createElementNS(svgns, "polygon");
star.setAttributeNS(null, "points", "100,10 40,198 190,78 10,78 160,198");
star.setAttributeNS(null, "fill", "gainsboro");
svg = document.getElementById('site').appendChild(star);
star.id = "star";
Now you may think that creating a Bezier curve might require something more complex – this isn’t the case: we can use the same format here too:
var bezier = document.createElementNS(svgns, "path");
bezier.setAttributeNS(null, "d", "M40,125 C15,5 110,5 120,55");
bezier.setAttribute("fill", "none");
bezier.setAttribute("stroke", "#333");
bezier.setAttribute("stroke-width", "2");
svg = document.getElementById('site').appendChild(bezier);

bezier.id = “bezier”; At this point, all of our objects have been created – I profess that they haven’t all been positioned in ideal locations onscreen, but then this is all part of experimenting with code! Let’s move on and take a look at the second part of the code we’ve used in this demo, beginning with moving our viewBox dynamically.

Dissecting Our Code – the Functions Used

Although much of our code caters for creating the additional SVG objects, this is only part of the story – we’ve added in a handful of functions to illustrate how we might manipulate these SVG objects using nothing more than plain JavaScript.

Our first example takes care of moving the visible area of the SVG, by updating the values set for our viewBox:
// Move viewBox on click of circle
circleBtn.addEventListener('click', moveSVG, false);
function moveSVG() {
  a-= 10;
  svgBox.setAttributeNS(null, "viewBox", a + " " + a + " 200 150");
}

We can clearly see that the code used is standard JavaScript, but with one exception – we’ve used the setAttributeNS method to recalculate the position of our viewBox. If you remember from the previous section, we talked about the fact that SVG is a format that relies on the use of namespaces, so specifying it here avoids the risk of collision with other code on the page intended for other applications.

The second function we created is a very simple click-based event handler – for this, we simply put an alert on screen to confirm that a user has clicked on the star:
// Show message on click of star
star.addEventListener('click', click, false);
function click(e) {
  alert("star clicked!");
}
The third and final function is a little more complex but nothing complicated; here the setFillColor function is fired as soon as we click on the square SVG. This time around, we’re changing the color to a shade of light gray:
// Fill a shape with random colors
document.querySelector("#triangle").addEventListener('click', setFillColor, false);
function setFillColor() {
  var triangle = document.getElementById('triangle');
  var r = Math.floor(Math.random() * 255);
  var g = Math.floor(Math.random() * 255);
  var b = Math.floor(Math.random() * 255);
  triangle.style.fill = 'rgb(' + r + ', ' + g + ' , ' + b + ')';
Our demo isn’t complete though – we’ve also specified a handful of style rules to add some color (yes, even in black and white print!) to our demo, and a simple animation effect when hovering over the square SVG:
@import url('https://fonts.googleapis.com/css?family=PT+Sans');
body { font-family: "PT Sans", sans-serif; color: antiquewhite; }
#container { margin: 6rem; }
svg { border: 1px solid #000; font-size: 36px; }
circle { fill: slategrey; cursor: pointer; }
#triangle { fill: darkgrey; stroke: black; stroke-width: 1;
  transform: scale(0.5); width: 150px; cursor:pointer; }
#star { fill: antiquewhite; transform: translate(150px, 40px);
  cursor: pointer; }
#btn {
  cursor:pointer;
}

Phew – that was one monster deconstruct! That aside, it shows that we can manipulate SVG elements using nothing more than plain JavaScript, although one must weigh up whether it is worth the effort required if your project demands anything more than a simple effect using SVG. It is always worth considering if your solution can be achieved using plain JavaScript, although the pressures and demands on your time and project may mean that using a library is the most effective and practical option!

Animating Borders Using SVG

Although we may want to use JavaScript to manipulate our SVG graphics, I’m a great believer in the KISS principle (“Keep it Simple,...” – you get the idea!). There are occasions where creating something simple can have just as much (if not more) impact than a more complex affair.

To see what I mean, and for our next exercise, we’re going to create a simple, if somewhat unusual, effect. Let’s say you hover over an image which could be expanded - you would expect something to happen to indicate this, such as the level of opacity increasing, right? Or perhaps a border that shows or hides when hovering…?

This sounds pretty straightforward, right? We could easily create something in our sleep – nothing difficult here! But – what if we were to use animation to create something a little different? Sure, our border will still appear, but let’s just say that it won’t be quite what you might expect…

ANIMATING BORDERS WITH SVG

Intrigued? Let’s get cracking on our code:
  1. 1.

    We’ll start by extracting a copy of the pyramid folder that is the code download that accompanies this book – go ahead and save it to our project folder.

     
  2. 2.
    Next, we need to set up our base markup – for this, go ahead and open pyramid.html, then add the following lines of code immediately after the <h2> element:
        <svg height="490" width="655" xmlns:="http://www.w3.org/2000/svg">
          <rect class="shape" height="490" width="655" />
          <div class="content">
            <img src="img/pyr.png">
            <p>Pyramids at Giza, Eygpt</p>
          </div>
        </svg>
     
  3. 3.

    If we run our demo now, we clearly won’t see anything of real interest, save for a picture of the Pyramids! Clearly, we need to add some animation, so go ahead and create a new file called pyramid.css in the css subfolder.

     
  4. 4.
    There are a few styles required, although nothing too heavy – we will add them block by block, starting with some rules to style the original markup and position our image:
    @font-face { font-weight: normal; font-family: 'pt_sansregular'; src: url('../font/pt_sansregular.woff') format('woff'); font-style: normal; }
    html, body {text-align: center; height: 100%; overflow: hidden;}
    body { font-family: 'pt_sansregular', sans-serif; padding: 2rem;
      font-size: 1.125rem; }
    img { position: relative; filter: sepia(10); }
     
  5. 5.
    In order to facilitate the required animation effect, we will make use of a container – for this, add the following code, leaving a line blank after the previous rule:
    .container { position: relative; top: 0.625rem; margin: 0 auto;  width: 40.9375rem; }
     
  6. 6.
    This next block of code takes care of hosting our image – for this, we’re creating a <rect> element and applying a standard CSS transition on three elements:
    rect { stroke-dasharray: 150 210; stroke-dashoffset: 0; stroke-width: 3px; fill: transparent; stroke: #b491a1; border-bottom: 0.3125rem solid black; transition: stroke-width 1s, stroke-dashoffset 1s, stroke-dasharray 1s; }
     
  7. 7.
    For the animation to kick in, we need to apply a :hover – add the following rule to take care of this for us:
    .container:hover rect { stroke-width: 0.375rem; stroke-dashoffset: 0; stroke-dasharray: 2560; }
     
  8. 8.
    These last two rules deal with styling our text, and positioning it as desired within our SVG:
    .content { font-size: 1.375rem; line-height: 2rem; letter-spacing: 0.5rem; color: #fff; top: -29.875rem; position: relative; color: #b491a1; }
    .content p { margin-top: 0.3125rem; }
     
  9. 9.

    At this point, go ahead and save the file – if we preview the results of our work, we should see something akin to the screenshot shown in Figure 10-2.

     
../images/461821_1_En_10_Chapter/461821_1_En_10_Fig2_HTML.jpg
Figure 10-2

Animating border trick

Hopefully you will agree that this is something different – the style may not appeal to everyone, but then again, I’ve not always been one for conforming to the norm! Although there is nothing in this code that we not seen before, it’s worth taking a few moments to review it in more detail, to understand exactly how it works.

Dissecting the Demo

If we take a look at the markup for our demo, we can see the bulk of our demo is contained within a standard SVG object that sits inside the .container div. Inside this SVG we use a <rect> that provides the border effect, along with the content div that houses both the image and image label.

The key to making it work lies in the style rule applied to the <rect> element and the associated hover event. In this case, we’ve applied three stroke values, namely stroke-dasharray, stroke-dashoffset, and stroke-width. The first controls the length of each dash around the image, interspersed with the whitespace; stroke-dashoffset controls at what point we start the border, and stroke-width for the thickness of this border.

We start by setting dashes of 150 units, followed by spaces of 210 units wide; we want this to start from point zero, so stroke-dashoffset is not needed and therefore set to zero. At the same time, our border is set to 0.1875rem, or 3px thick.

When hovering over the .container element, this is set to inherit child elements, so it includes the image and text; the border thickness increases to 0.375rem or 6px. At the same time, we no longer want our border to have gaps, so set it to 2560; this has the effect of showing one long dash around the entirety of the image.

Okay – let’s move on: time for something different, methinks! I don’t know about you, but I’ve lost count of the number of sites that use the same format for navigating around the site. Sure, it might be the classic hamburger approach for mobile or responsive sites, but in many cases, it is likely to be the typical linear affair. I think it’s time to change that and go for something a little more unusual…

Creating Menus Using GSAP and SVG

Hopefully that last comment has left you a little intrigued – if so, let me explain all:

What if we could create the basis for a menu, but this time use animation to blow it up like an expanding circular overlay, over our main text? Fortunately, one kind soul has already created something that shows off the power of SVG; it uses the GSAP animation library (available from https://www.greensock.com ).

That kind soul (and where credit is due), is Breno Thales; you can see his original version at https://codepen.io/brenothales/pen/MKaxaq . Our version will use a slightly different color scheme, but the functionality will remain unchanged.

CREATING MENUS USING GSAP

Before we get started, it’s worth nothing that our next demo will be created using the MorphSVG plug-in, from the GSAP suite. As this plug-in is a commercial offering, we’ll be using a trial version, which will only work in certain URLs such as Codepen.

With this in mind, let’s make a start with our code:
  1. 1.

    First, we need to extract a copy of the menu folder from the code download that accompanies this book – go ahead and save it to our project folder.

     
  2. 2.

    To create our demo, we need to browse to https://codepen.io in your usual browser – once there, click on Create | New Pen.

     
  3. 3.

    We’re making use of three external libraries for this demo, so click on Settings | JavaScript, and add each of the following links into the boxes at the bottom, underneath External Resource search...

    //cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js

    //cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/TweenMax.min.js

    //s3-us-west-2.amazonaws.com/s.cdpn.io/16327/MorphSVGPlugin.min.js?r=182

     
  4. 4.

    From the code we downloaded in step 1, copy and paste the contents of the markup.txt file into the HTML pane.

     
  5. 5.

    Next, go ahead and copy and paste the contents of the styles.txt file into the CSS pane within Codepen.

     
  6. 6.

    We’re almost done – to tie everything together, and make our menu operate, we need to add our script. For this, copy the contents of the script.txt file into the JS pane.

     
  7. 7.

    At this point hit the Save button – you can either save it as Anonymous, or under your own account if you already have one with Codepen.

     
If all is well, we should see something akin to the screenshot in Figure 10-3.
../images/461821_1_En_10_Chapter/461821_1_En_10_Fig3_HTML.jpg
Figure 10-3

Our finished menu using GSAP

Hopefully you will agree that this could prove to be a more interesting way to display our content! The real beauty is that we could potentially use this effect elsewhere – how about as an image overlay?

It would certainly be a more unusual option, but who says the rule book can’t be broken sometimes? That aside, this demo contains some useful tips, particularly when animating content with the GSAP library – let’s dive in and take a look at our code in more detail.

Understanding How It Works

If we take a closer look at the code we put together in our Codepen demo, it might at first glance look a little complex. However, this example relies on one simple trick – we’re animating content from one state to another but doing it in stages (just like a bus travels from point A to B via C).

A large part of our markup forms the background container, inside we start with an empty placeholder for our circular menu (#menu). We also specify some simple markup to create a series of blocks (within the .navbar class), which will act as our background content. The real meat of our markup though is in two SVG group elements, inside of which are a number of SVG paths: the animgroup takes care of animating the circular menu, while the linegroup creates the fake menu entries.

To make our demo work, we’ve used the morph.to method from the morphSVG plug-in, to animate the content. This sets the starting point as #state1, which we then morph to #state2 using a Sine.easeIn easing effect. We then immediately jump back to #state1 and morph through to #state3, this time using an Elastic.easeOut easing effect. We then finish off the demo with two event handlers, which check to make sure we are at point zero (i.e., can animate to the circular menu) or reset the code so that the animated menu can reverse direction and be closed back to our original content.

Okay – let’s change tack and move onto something completely different: lazy loading. I’m sure you will be familiar with the principle of placeholders that are subsequently replaced with the real image, right? Well, instead of inserting lots of lo-res images as placeholders, how about using SVG to create something similar?

Lazy Loading with SVG

As a principle, Lazy loading is nothing new – it’s been around since at least 2003; it’s a useful technique to delay loading of image content until the last possible moment. It’s particularly important in an age where mobile usage is becoming more popular than normal desktop usage, and removing bottlenecks in loading pages is an essential part of any designer’s work.

The challenge we have though is that we clearly need something to act as a placeholder for each image. Ordinarily we might use a low-resolution image – this would work, but calling another image as part of the solution defeats the purpose of what we’re trying to achieve!

Instead, why not use SVG? It might not seem obvious, but as a format it lends itself really well to this technique:
  • We can scale it to any size without loss of quality;

  • It can be stored inline as markup, without the need to call a separate resource;

  • It can be reused throughout the site, avoiding the need to create or manage multiple low-res placeholder images.

There are a couple of ways we can create a lazy loading effect that makes use of SVG – in both cases, we use SVG as the placeholder. The image can then be introduced once a random timeout value has passed, or we use a window.onload() to prevent loading until everything else is in place. To see how it works, let’s dive in and take a look at some example code in more detail.

LAZY LOADING WITH SVG

For our next demo, we’ll use the first of the two methods – we’ll load an image once a randomly set timeout value has passed (more on this later). This is to simulate the time it might take for other content to appear, which may vary; once done, the image can then be displayed in all its glory. The image we will use is from the Unsplash image library; it is one of a vintage camera, and it is available from https://unsplash.com/photos/1oke6gf5vKo .

This example works very well when run locally or in a Codepen – see my version online at https://codepen.io/alexlibby/pen/ELrXYz . Note though, that it will take a few seconds for the image to appear – it pays to be patient!

Let’s crack on with creating our demo:
  1. 1.

    First, go ahead and extract a copy of the lazyload folder that is in the code download that accompanies this book; save it to our project folder.

     
  2. 2.

    Next, we need to add in our SVG markup – for this, copy and paste the contents of the markup.html file in just below the opening <body> tag and comment in our file.

     
  3. 3.
    We need a little styling to position the image – for this, add the following rules to a new file, saving it as lazyload.css in a css subfolder:
    @font-face { font-family: 'pt_sansregular'; src: url('../font/pt_sansregular.woff') format('woff'); font-weight: normal; font-style: normal; }
    body { margin: 2rem; font-family: 'PT Sans', sans-serif;
      font-size: 1.125rem; }
    .imageContainer { float: left; height: 0; padding-bottom: 33.33%; position: relative; width: 50%; }
    svg, .image { height: 200%; left: 0; position: absolute;
      width: 100%; }
    .image { opacity: 0; transition: opacity 300ms; background-size: cover; }
    .image-displayed { opacity: 1; }
    @media all and (max-width: 480px) {
      .imageContainer { padding-bottom: 66.67%; width: 100%; }
    }
     
  4. 4.
    To finish it all off, there a little JavaScript we need to add to provide the final effect – for this, go ahead and copy and paste the contents of script.js into a new file in the js subfolder, saving it as lazyload.js:
    setTimeout(() => {
      var elem = document.querySelector('.image');
      elem.style.backgroundImage = 'url(https://images.unsplash.com/photo-1510141365970-ac1f0f80b1a5';
      elem.classList.add('image-displayed');
    }, Math.random() * 2000 + 500);
     

For the purposes of this demo, we’ve set a random time, to simulate the fact that resources do not always load in the same order consistently. I would recommend though that in production use, the time taken to load should be tested, and that a value to cover this plus some leeway, be used instead.

  1. 5.

    Save the file as lazyload.html – if we preview the results in a browser, we should see something akin to the screenshot shown in Figure 10-4.

     
../images/461821_1_En_10_Chapter/461821_1_En_10_Fig4_HTML.jpg
Figure 10-4

Lazy loading an image

For such a useful effect, this surely has to be one of the simplest ones to implement! If we examine our code in detail, it might look like we have a fair amount in use, but much of this is for the SVG placeholder. The real crux of the code is in the small amount of JavaScript that we use – let’s take a look to see how it works in more detail.

Breaking Apart Our Code

We begin first with setting a div with a class of imageContainer ; this is purely to group the two parts of our demo together. The first part of our code is our SVG image; we’ve used a random one in our code, but this could easily be a company logo or motif. It doesn’t really matter what we use, although I would recommend keeping it simple. The more complex our SVG, the more code it requires; we’re not going to see it for too long, so detail will be redundant.

The second part of our demo is really simple – we include a single div (with a class of image) as a placeholder for our final image. This is loaded using a plain vanilla script; in this, we get a reference to the aforementioned div, then set our picture from the Unsplash library as the background image. We then add a class of image-displayed; it’s not used in our demo but would act as a trigger to confirm that the image has been loaded on the page.

Note

If you decide to try this in a Codepen demo, then you may want to replace the font declaration with this line, to allow it to work in the same way as our offline demo: @import url(' https://fonts.googleapis.com/css?family=PT+Sans ');

I hope you’re suitably rested after that mini demo, as I have a real corker of an exercise coming up for you! For our next demo, we’ll be revisiting a subject we’ve already touched on earlier in the book. – creating charts. Remember how we created various types, such as bar and pie charts? They were easy enough to do; this time though, we’ll put a whole new spin on things, and incorporate a simple pie chart into a template-based framework.

Creating Template-Based Charts

Back in the day, we didn’t have that – we had to do it by hand…

A phrase that often comes to mind when working with template libraries – it serves as a reminder that the days of cranking code markup have long since gone! (Although I still think that sometimes it would be nicer to be able to get back to grassroots, so to speak – but I digress…)

Anyway – enough reminiscing: our next demo will focus on using a template library to create an SVG chart. However, we’re not going to use one of the “big boys” like Angular or React, but something different: Ractive. Created by the IT team at the Guardian newspaper here in the UK, it’s a lightweight framework that operates in much the same way as its bigger cousins, but without all of the overhead or baggage that come with the larger libraries.

If you are interested in learning more about Ractive, then I would recommend perusing my book, Beginning Ractive.js (Apress, 2017).

For the demo, we’re going to use Ractive to create a standard pie chart that displays population counts for five countries, namely Italy, Mexico, France, Argentina, and Japan. We’ll add in our data from a JSON source using AJAX and use a couple of libraries to create a color scheme for our chart, based on two given colors. Our demo is based on a version created by Marcello la Rocca; I’ve simplified some of the functionality, reduced the data files in use, and updated both Ractive and jQuery to more recent versions.

CREATING TEMPLATE-BASED CHARTS – PART 1

Before we go ahead with developing our code, there is one small thing we need to do, and that is set up a local webserver. Unfortunately, JSON files can’t be loaded from the file system – the only way to do this is under the HTTP protocol.

For this, we can use any local web server, such as XAMPP ( https://www.apachefriends.org ), or even the simple HTTP-Server available from NPM at https://github.com/indexzero/http-server is perfectly fine for this purpose.

Assuming we have a local working server installed, let’s make a start on our code:
  1. 1.

    We’ll begin by extracting a copy of the ractive folder from the code download that accompanies this book – go ahead and save it to our project area.

     
  2. 2.
    Next, go ahead and open ractive.html – we now need to add in our markup. There is a fair bit to add in, so we’ll go through it block by block, starting with the container pie <div> and opening <script> tag:
    <div id="pie"></div>
    <script id="myTemplate" type='text/ractive'>
     
  3. 3.
    We can now add in our opening tags and title:
          <div class="panel panel-default">
            <div class="panel-heading">
              <h2 class="panel-title">Beginning SVG: Creating Population Charts</h2>
            </div>
     
  4. 4.
    Next in comes the main part of our SVG – this first block takes care of creating the base pie chart:
            <div class="panel-body">
              <svg width=375 height=400>
                <g transform="translate(180, 200)">
                  {{# Pie({center: center, r: r, R: R, data: countries, accessor: accessor, colors: colors}) }}
                    {{# curves:num }}
                      <g transform="translate({{ move(sector.centroid, expanded[num]) }})">
     
  5. 5.
    Our demo uses a gradient effect to add some styling to each tranche in the pie chart; this is taken care of by this block:
             <linearGradient id = "grad-{{ num }}">
               <stop stop-color = "{{ color_string(color) }}" offset = "0%"/>
               <stop stop-color = "{{ lighten(color) }}" offset = "100%"/>
             </linearGradient>
             <path d="{{ sector.path.print() }}" fill="url(#grad-{{ num }})" />
     
  6. 6.
    We can’t have a pie chart without some form of labelling – we add the details using this <text> element:
               <text text-anchor="middle" transform="translate({{ point(sector.centroid) }})">{{
               item.name }} ({{ item.population }}m)</text>
             </g>
     
  7. 7.
    Last but by no means least, we need to close out our demo with a handful of tags, including one to indicate that our population figures are in the millions:
                {{/ curves }}
              {{/ end of pie}}
            </g>
          </svg>
          <p class="tagline">Numbers shown in millions</p>
        </div>
      </div>
    </script>
     
  8. 8.
    To tie it all together, we need to place a call to Require.js, to reference each script module as needed:
    <script data-main="js/demo" src="js/require.js"></script>
     

At this point, save your work and take a breather for a moment – we have our markup in place, but it won’t come to life until we add in our JavaScript code.

Ractive works on the basis that data is stored away from the markup in one big configuration object; for now, let’s add that block in, before we go through it in more detail at the end of this next exercise.

CREATING TEMPLATE-BASED CHARTS – PART 2

In the second half of this project, we’re going to concentrate on the JavaScript code that is required to make our demo work – it might seem like a lot, but a good chunk of this takes care of calling in each script library as needed, along with loading our data from JSON files using AJAX.

As before, we’ll go through it in more detail at the end of this exercise, but for now let’s get it up and running:
  1. 1.

    We’ll start by opening a new document in your normal text editor, saving it as demo.js in the js subfolder of our ractive folder.

     
  2. 2.
    Next, go ahead and add in each block in turn – this first one configures Require.js, to point it to the relevant libraries that we will make use of in our demo:
    requirejs.config({
      "baseUrl": "js/dist/amd/",
      "paths": {
        "jquery": "../../jquery.min",
        "ractive": "../../ractive",
        "Colors": "../../colors",
        "util": "../../util",
        "pie": 'pie'
      }
    });
     
  3. 3.
    With Require.js configured, next comes the call to each library:
    require([
      'jquery',
      'ractive',
      'pie',
      "Colors",
      "util"
    ], function($, Ractive, Pie, Colors, util) {
     
  4. 4.
    We now start the core part of our code – the first step is to set the use strict statement, to help enforce better error checking in the browser. We then follow this with a function to load the data from a JSON file (this could easily be extended to use multiple files):
      "use strict";
      function loadCountries(dataset) {
        $.ajax({url: dataset, headers: {'Content-Type': 'application/json'}, processData: false})
          .done( function ( data ) {
            data = JSON.parse(JSON.stringify(data));
            ractive.animate('countries', data);
          })
          .fail(function (err) { console.log("ERROR LOADING JSON", err);
        });
      }
     
  5. 5.
    Our pie chart of course needs some color – for this, we’re using the Colors library to mix up each color in turn, based on two given colors (a shade of dark gray-blue and light gray-orange):
    var palette = Colors.mix({r: 112, g: 128, b: 144}, {r: 250, g: 235, b: 215});
     
  6. 6.
    Next in comes the core of our code – the Ractive object; here we initialize Ractive with each of the various sections, beginning with the target location and template to use:
      var ractive = new Ractive({
        el: 'pie',
        template: '#myTemplate',
     
  7. 7.
    We need to specify a data block – this covers a number of different pieces of data, such as specifying our pie chart, center of our chart, the radius and size, along with the dataset to use:
        data: {
          Pie: Pie,
          center: [0, 0],
          r: 20,
          R: 150,
          countries: [],
          expanded: [],
          datasets: [{label: "Mixed", filename: "json/countries.json"}],
          accessor: function (x) {
            return x.population;
          },
          colors: util.palette_to_function(palette),
          move: function (point, expanded) {
            var factor = expanded || 0;
            return (factor * point[0] / 3) + "," + (factor * point[1] / 3);
          },
          point: function (point) {
            return point[0] + "," + point[1];
          },
          lighten: function (color) {
            return Colors.string(Colors.lighten(color));
          },
          color_string: Colors.string
        }
      });
     

It is worth noting that our data block also includes functions to create the color scheme used, along with positioning each data label in our chart.

  1. 8.
    We finish with placing a call to the loadCountries method, to get and load our JSON data file:
      loadCountries(ractive.get('datasets')[0].filename);
    });
     
  2. 9.

    At this point, go ahead and save the file – if all is well, we should see the screenshot shown in Figure 10-5 when previewing the results in a browser:

     
../images/461821_1_En_10_Chapter/461821_1_En_10_Fig5_HTML.jpg
Figure 10-5

Our finished chart, displayed using Ractive

Dissecting the Code

If you were asked to write a summary of this demo, you might be forgiven for thinking where it is that one would start to explore how it works, there is so much code! Our demo looks complex, but in reality, it is simpler than it looks: a good chunk is there to support Require.js and the loading of data. The crux of our demo centers around two files – ractive.html and demo.js; these contain the markup and script required to make our demo operate. Let’s take a look at the code in more detail, starting with ractive.html.

If you open up ractive.html, a large chunk of it contains standard HTML markup; you will notice that much of this code has been wrapped in a <script> block. The difference here is in the use of the <....type="text/ractive"> tag; this is used by Ractive to define the template in our demo (more on this shortly).

Take a closer look at the code though, and you will see several examples of {{...}} in the code. These are used as placeholders for our content – take, for example, the item.name and item.population values in line 27.

These correspond to the name and population values in our JSON file; the {{# curves: num }} loop runs through each item in the JSON file and populates the values in our markup. It’s worth noting though that we make use of a number of functions in our placeholders – a good example is in line 23, where we call the function {{ lighten(color) }} to create a lighter shade of one of our base colors, before inserting it into our markup.

Exploring the Ractive Script Code

Although the markup plays an important role, it’s only when you view the script does it all begin to come together and make more sense. If we open the demo.js file, we can see two blocks at the start – the first configures Require.js to point it to the script libraries we will use. The second initiates them as a dependency; the script files are not called until they are needed in the script.

Next up comes a request to load in our JSON file – for this we are using standard jQuery for convenience; we could use JavaScript (and given this is the only time it is used, it might be no bad thing to remove a big dependency!). Before we get to our Ractive script though, we have one final variable definition – this uses the Colors library to mix two colors to help create our color scheme for the chart.

With these definitions out of the way, we now move onto our Ractive object – this is made up of three elements, namely el, template, and data. The first, el, is our target for where the compiled template will be inserted – in this case, the div with an ID of pie. The template attribute corresponds to the template we will use; remember the script block we created in our markup file, which has the ID of myTemplate? This is what we will use to generate our final markup.

The third and final section is data – this contains all of the functions and attributes used in our markup. This can contain all kinds of content; this might range from simple values such as r or R (used to specify the radius of our pie chart), through to datasets (used to specify which data files to use) and colors, where we create our palette based on the two defined base colors.

We also have a couple of extra functions of note – move and point handle the location of each label, while lighten is used to create a lighter shade of color for our palette. We then round out our demo with a call to loadCountries, to initiate our Pie chart with the appropriate data from the JSON file.

I would strongly recommend taking a look at the compiled code from within your browser’s DOM inspector – the compiled version will look something like the screenshot shown in Figure 10-6. It will help you to understand how the source code has been transformed into the final solution.
../images/461821_1_En_10_Chapter/461821_1_En_10_Fig6_HTML.jpg
Figure 10-6

The compiled Ractive code

It might seem a lot of code, but this is a fairly in-depth example – partially to show off that complexity should not be an issue when using SVG, but also to show a real-world example of how SVG can be incorporated into sites written using frameworks such as Ractive. It is worth spending time understanding how this is put together – you may not use Ractive (although it is a great tool to use), but many of the principles also apply to the bigger versions such as Angular or React.

Okay – let’s move on: we’re almost at the end of our journey through using SVG, but to help round out our adventure, we will finish with some smaller, but equally interesting examples, of how we might use SVG in a more practical context in our projects.

A Parting Shot

Phew – that last demo was a real monster! Time for something a little lighter, methinks…!

Throughout the course of researching for this book, I’ve come across a fair few examples of using SVG in a practical context; this included very simple to examples to some more detailed solutions. There are a few that I thought were worthy of a mention – they show that with a bit of ingenuity, it’s possible to produce some really original effects. Let’s take a look at each of them in turn, beginning with an example that is perfect for a restaurant or food outlet.

Tilting UI Effect

Our first example comes courtesy of the developer Neil Pearce – he’s used a mini library called Tilt.js. Created by Gijs Rogé, the library itself can be downloaded from https://gijsroge.github.io/tilt.js/ .

Neil has put this library to great use, by creating two cards that display information from a mocked-up page that wouldn’t be out of place on a hotel website. You can see the demo on Codepen at https://codepen.io/2975/pen/WJwxYv  – try hovering over each card in turn: notice how it tilts slightly as you move the mouse over each (Figure 10-7):
../images/461821_1_En_10_Chapter/461821_1_En_10_Fig7_HTML.jpg
Figure 10-7

Making use of tilt.js

In this instance, the demo illustrates how we can make use of other libraries to manipulate SVG elements with little difficulty; the animation effect is managed within the SVG, while the tilting effect comes from the Tilt.js library.

Panning and Zooming Images

This next example features a simple take on an age-old problem – viewing images close up, particularly those with lots of detail.

The developer Anders Riutta has created a library that enables anyone to pan or zoom in on an SVG image for this purpose; it can be downloaded from GitHub at https://github.com/ariutta/svg-pan-zoom . We can see it in use with one of the demos provided on the main website; as an example, Figure 10-8 shows an inline SVG image of a tiger in close-up.
../images/461821_1_En_10_Chapter/461821_1_En_10_Fig8_HTML.jpg
Figure 10-8

Panning and zooming an SVG image

This is just one way of navigating around SVG images – the library offers support for a host of different options, such as embedded SVGs, custom events, animation, and using custom controls.

You can see the original demo on the main website at http://ariutta.github.io/svg-pan-zoom/demo/inline.html .

Tracking Progress

Our final example makes use of one of SVG’s key strengths – the ability to use the <path> element to create any kind of shape, simply by providing suitable coordinates.

This is put to good use in the Progressbar.js library; created by Kimmo Brunfeldt, this library can be downloaded from http://kimmobrunfeldt.github.io/progressbar.js/ . It’s designed for use in modern browsers, released within the last two to three years; this includes IE10 and 11! The library produces a clean and slick design – we can see it in action in a screenshot shown in Figure 10-9.
../images/461821_1_En_10_Chapter/461821_1_En_10_Fig9_HTML.jpg
Figure 10-9

Animating a SVG progress bar

To really understand how SVG plays its part in this library, I would recommend taking a peek at the code behind this example; Figure 10-10 shows what the SVG code looks like from our example.
../images/461821_1_En_10_Chapter/461821_1_En_10_Fig10_HTML.jpg
Figure 10-10

An example of how Progressbar.js is used

The great thing about this library is that we don’t even have to provide the path coordinates to use if we want to use a standard shape; Progressbar.js provides a number of pre-built options such as circle or line. If though we want to push the boat out (so to speak), we can of course provide our custom path coordinates in the markup and let the library take care of the rest…!

Summary

SVG as a format is hugely versatile – unlike images or other graphic formats, we can manipulate elements within with ease, using nothing more than standard JavaScript (or libraries), and plain CSS styling. Over the course of this chapter, we’ve worked through a number of examples to illustrate how we might use SVG in a real-world example; let’s take a moment to review what we have learned.

We kicked off with a quick tour on how to create or manipulate SVG objects using vanilla JavaScript – some might argue that this should be nearer the start of the book, but we quickly learned how much extra code (and time) is required to add in simple shapes - which could indeed put beginners off! Making use of a library will frequently be a more efficient use of time and resources.

Next up came a look at an interesting take on animating borders using SVG – this illustrated a perfect means of animating a simple change that adds a certain edge to an otherwise plain image, using nothing more than standard SVG animation.

Our next demo took animation up a notch and explored part of the Greensock GSAP animation library; we saw how the morphing tool can provide an original solution, which stands apart from other menus you may have seen online.

We then moved onto exploring a time-honored technique of lazy-loading images – this is nothing new, but our version swapped in SVG images as placeholders for what would otherwise be low-resolution images. We covered how this reduces the number of calls for extra resources, so it ultimately reduces the load on the server and helps retain page speeds.

Our final large demo explored how we might create template-based charts using a framework such as Ractive; we learned how we can use such a library to swap in data and text to a standard chart, so that ultimately our chart can be set as a reusable template for future projects. We then rounded out the chapter with some smaller examples of how SVG can be used in a practical context; this was to show that SVG is a versatile format, and that you are really only limited by your imagination!

Phew – well, all good things must eventually come to a close, as we reach the end of this book; I hope you’ve enjoyed our adventure through the world of SVG as I have writing this book.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.144.194