How to Build an Interactive Infographic using Vuejs - SVG - GSAP

How to Build an Interactive Infographic using Vuejs - SVG - GSAP

This article presents a modern approach to building an interactive infographic. You sure can have plain infographic with all the information available upfront — without any user interaction. But, thinking of building an interactive experience — changes the technology landscape we choose. Therefore, let’s understand first, why Vue.js? And you’ll see why GSAP (GreenSock Animation Platform) and SVG (Scalable Vector Graphics) become obvious choices.

Have you ever had a requirement in which you had to design and build an interactive web experience but the grid system fell short? Furthermore, the design elements turned into unusual shapes that just wouldn’t fit into the regular web layouts? In this article, we’re going to build an interactive infographic using Vue.js, SVG and GreenSock by using dynamic data and unusual layout.

This article presents a modern approach to building an interactive infographic. You sure can have plain infographic with all the information available upfront — without any user interaction. But, thinking of building an interactive experience — changes the technology landscape we choose. Therefore, let’s understand first, why Vue.js? And you’ll see why GSAP (GreenSock Animation Platform) and SVG (Scalable Vector Graphics) become obvious choices.

Vue.js provides practical ways to build component-based, dynamic user interfaces where you can manipulate and manage DOM elements in powerful ways. In this instance, it’s going to be SVG. You can easily update and manage different SVG elements — dynamically — using only a small subset of features available in Vue.js — some of the staple features that fit the bill here, are, data binding, list rendering, dynamic class binding to name a few. This also allows you to group relevant SVG elements together, and componentize them.

Vue.js plays nice with external libraries without losing its glory, that is GSAP here. There are many other benefits of using Vue.js, one of which is that, Vue.js allows you to isolate related templates, scripts, and styles for each component. This way, Vue.js promotes modular application structure.

Vue.js also comes packaged with powerful lifecycle hooks that let you tap into the different stages of application to modify application behavior. Setting up and maintaining Vue.js applications doesn’t require a big commitment, meaning you can take phased-approach to scale your project as you go.

The infographic is very light-weight in a visual sense, as the main aim of this article is to learn how to think in terms of data, visual elements, and of course, Vue.js — the framework that makes all the interactivity possible. In addition, we’ll use GreenSock, a library for animating SVG elements.

We’ll start with:

  1. The overview of the data for infographic;
  2. SVG image preparation;
  3. An overview of Vue components in context of the SVG artwork;
  4. Code samples and diagrams of key interactivity.

The infographic that we’re going to build is about Tour De France, the annual bicycle racing event held in France.

Overview Of Tour De France Data

In infographic design, data drives the design of your infographic. Therefore, while planning your infographic design, it’s always a good idea to have all data, information, and statistics available for the given subject matter.

During Tour De France of 2017, I learned everything about this biggest cycling event that I could in 21 days of the game in July, and I familiarized myself with the subject.

Basic entities of the race that I decided to go for in my design are,

  • Stages,
  • Teams,
  • Routes,
  • Winners,
  • Length and classifications of each routes.

This next part of the process depends on your thinking style, so you can be creative here.

I created two sets of data, one for stages and other for teams. These two datasets have multiple rows of data (but within limit)  —  which matched with two wheels of the bicycle with multiple spokes in each. And that defined the key element of the design, The Bicycle Art that you saw at the beginning  —  where each spoke will be interactive & responsible to drive what information is revealed on screen.

I mentioned within limits above, because what we’re aiming for in this instance is not a full-blown data-visualization in context of big data but rather an infographic with high-level data.

Therefore, spend quality time with data and look for similarities, differences, hierarchy or trends that can help you convey a visual story. And don’t forget about the amazing combination of SVG and Vue.js while you’re at it, as it will help you bring about the right balance between information (data), interactivity (Vue.js) and design elements (SVG Artwork) of infographic.

Here’s the snippet of a stage data object:

{
    "ID": 1,
    "NAME": "STAGE 01",
    "DISTANCE": "14",
    "ROUTE": "KMDÜSSELDORF / DÜSSELDORF",
    "WINNER": "THOMAS G.",
    "UCI_CODE": "SKY",
    "TYPE": "Individual Time Trial",
    "DATE": "Saturday July 1st",
    "KEY_MOMENT": " Geraint Thomas takes his first win at 32"
}

And team data object snippet as below:

{
    "ID": 1,
    "UCI_CODE": "SKY",
    "NAME": " TEAM SKY",
    "COUNTRY": "Great Britain",
    "STAGE_VICTORIES": 1,
    "RIDERS": 8
}

This infographic is operated by a very simple logic.

SVG Preparation

Having a couple of datasets and a rough concept of bicycle art ready, here’s the static SVG CodePen of the infographic I came up with.

We have created only one spoke for each wheel, that is because we’ll dynamically create rest of the spokes using a number of records found in the dataset, and animate them using GreenSock Library.

The workflow to create this SVG code is also very simple. Create your Infographic artwork in Adobe Illustrator and save as SVG. Make sure to name each group and layer while working in Illustrator, because you will need those ids to separate parts of SVG code that will eventually populate `` area of Vue components. Remember that layer names given in Illustrator become element ids in SVG markup.

You can also use SVGOMG and further optimize SVG code exported from Adobe Illustrator.

Important Note: If you use SVGOMG to optimize SVG markup, your code certainly will look neat, but note that it will convert all elements into with d attribute. This results into losing x and y values of the rectangle, in case you wish to adjust few pixels manually later-on.

Second thing, make sure to uncheck Clean Id option (right-hand side options in SVGOMG interface), this will help maintain all groups and ids intact that were created in Illustrator.

Vue Component Overview

Even if interactivity and data-flow in your infographic project is quite simple in nature, you should always take a moment to draw up a tree diagram of components.

This will especially help in case you’re not using any shared-data mechanism, where child components are dependent on the values sent from the parent component (i.e. via props) or vice-versa (i.e. this.$emit events). This is your chance to brainstorm these prop values, emit events and local data — and document them before starting to write the code.

Diagram above is the snapshot of Vue components that is partially derived from interactivity requirements and partially based on SVG markup. You should be able to see how SVG markup will be split up based on this tree structure. It’s pretty self-explanatory from hierarchy view-point.

  1. Chain-wheel will imitate rotation of spokes.
  2. Stage component is the rear wheel that will list all 21 stages.
  3. Stage-detail component will display related information on a curved path (left-hand side).
  4. Team component is the front wheel that will list all participating teams on spokes.
  5. Team-detail component will display related information on a curved path (right-hand side).
  6. Navigation will include back and next button to access stages.

The diagram below represents the same Vue components seen above, but in the context of the infographic design.

Less is more — should be the approach you should try to take while working on similar projects. Think through the animation and transition requirements you have, if you can get away with using TweenLite instead of TweenMax — do so. If you have the option to choose elementary shapes and simpler paths over complex ones — by all means try to opt-in for light-weight elements that are easy to animate — without any performance penalty.

Next section will take you through an exciting part with GreenSock animation and Vue.js.

GreenSock Animation

Let’s take a closer look at:

  1. Text animation on a curved path;
  2. Spoke animation on a wheel.

Animating Text On A Curved Path

Remember the curve path seen around the bicycle wheel, that curved path is slightly bigger than the radius of the bicycle wheel. Therefore, when we animate text on this path, it will look as if it follows the shape of the wheel.

path and textPath is a sweet combination of SVG elements that allows you to set text on any path using xlink:href attribute.

<path id="curvedPath" stroke="none" fill="none" d="..."/>

<text>

  <textPath xlink:href="#curvedPath"
          class="stageDetail"
          startOffset="0%">
          {{ stage.KEY_MOMENT }}
   </textPath>

</text>

To animate text along the path, we’ll simply animate its startOffset attribute using GreenSock.

tl.fromTo( ".stageDetail", 1,

{
  opacity: 0,

  attr: { startOffset: "0%" }

},

{

  opacity: 1,

  attr: { startOffset: "10%" }

}, 0.5 );

As you increase the startOffset percentage, text will travel further through the circle perimeter.

In our final project, this animation is triggered every time any spoke is clicked. Now, let’s move on to a more exciting part of the animation.

Animating Stages/Spokes Inside The Wheel

It’s visible from the demo that stage and team components are similar in nature with couple of small differences. So, let’s focus on just one wheel of the bicycle.

The CodePen example below zooms in on just the three key ideas:

  1. Fetch stage data;
  2. Arrange spokes dynamically based on the data;
  3. Re-arrange spokes when stage (spoke) is clicked.

You may have noticed in the static SVG CodePen above that the spokes are nothing but SVG rectangles and text grouped together. I have grouped them together since I wanted to pick both text and rectangle for the purpose of animation.

<g v-for="stage in stages" class="stage">

    <rect x="249" y="250" width="215" height="1" stroke="#3F51B5" stroke-width="1"/>

    <text transform="translate(410 245)" fill="#3F51B5" >

      {{ stage.NAME }}

    </text>

</g>

We will render them in `` area of the Vue component using values fetched from the data-source.

When all 21 stages are available on screen, we’ll set their initial positions by calling, let’s say, setSpokes().

// setSpokes()

let stageSpokes = document.querySelectorAll(".stage")
let stageAngle = 360/this.stages.length

_.map(stageSpokes, (item, index) => {
    TweenMax.to(item, 2, 
    { rotation: stageAngle*index, 
      transformOrigin: "0% 100%"
    }, 1)
}

Three key elements of setting the stage are:

  1. Rotation
    To rotate spokes, we’ll simply map through all elements with className stage, and set dynamic rotation value that is calculated for each spoke.
  2. Transform Origin
    Notice transformOrigin value in the code above, which is as important as index value, because “0% 100%” enables each spoke to rotate from the center of the wheel.
  3. stageAngle
    This is calculated using total number of stages divided by 360-degree. This will help us lay every spokes evenly in 360-degree circle.

ADDING INTERACTIVITY

Next step would be to add click-event on each stage to make it interactive and reactive to data changes  —  hence, it will breathe more life into an SVG image!

Let’s say, if stage/spoke is clicked, it executes goAnimate(), which is responsible to activate and rotate the stage being clicked using the stageId parameter.

goAnimate (stageId) {

  // activate stage id
  this.activeId = stageId

  // rotate spokes

}

We’ll use DirectionalRotationPlugin …which is a key ingredient for this interactivity. And yes, it is included in TweenMax.

There are three different ways of using this plugin. It animates rotation property in 1) clockwise, 2) counter-clockwise and 3) in the shortest distance calculated to the destination.

As you’d have guessed by now, we’re using the third option to rotate the shortest distance between the current stage and new stage.

Review the CodePen above and you’ll see how Stage 01 is constantly moving around the circle, leaving its original spot for new active stage at 0-degree angle.

First, we need to find the angle of a stage being clicked, and interchange its rotation with Stage 01. So, how do we find the rotation value of the stage being clicked? Check out the diagram below.

For example, if Stage 05 is clicked (as you can see above), the journey from Stage 01 to Stage 05  —  requires 4 x angle-value.

And therefore, we can get the correct angle using, (Active stage Id - 1) * 17 degree, followed by ‘_short’ string postfix to trigger directional rotation plugin.

angle = 360/21 stages = 17
activeId = 5
new angle = ((activeId-1)*angle)+'_short'
          = ((5-1)\*17)+'_short'
          = 68

The final goAnimate() function will look something like below:

_.map(spokes, (item, index) => {

  if(activeId == index+1) { 
    // active stage
    TweenMax.to(item, 2, 
    { rotation: 0+'_short', 
      transformOrigin: "0 100%"
    })   

  } else if (index == 0) { 
    // first stage
    TweenMax.to(item, 2,
    { rotation: (activeId*angle)-angle+'_short',
      transformOrigin: "0 100%"
    })

  } else {
    TweenMax.to(item, 2, 
    { rotation: index*angle+'_short', 
      transformOrigin: "0 100%"
    })
  }

}) // end of map

Once we have the rear wheel ready, the front wheel (for team) should follow the same logic with a couple of tweaks.

Instead of stage, we’ll fetch team data and update registration point of transformOrigin attribute to enable spokes generation from opposite registration point than the stage wheel.

// set team spokes

map(teamSpokes, (index, key) => {
  TweenMax.to(index, 2, 
  { rotation: angle*key, 
    transformOrigin: "100% 100%"
  }, 1)
})

Conclusion

Creating interactive and engaging infographics requires you to be analytical with the data, creative with visuals and efficient with the technology you use, which in this case is Vue.js. You can further use these concepts in your project. As a closing note, I’ll leave you with this circular interactive color wheel below that uses an idea similar to the one we’ve discussed in this article.

Thank you for reading !

JavaScript Tutorial: if-else Statement in JavaScript

JavaScript Tutorial: if-else Statement in JavaScript

This JavaScript tutorial is a step by step guide on JavaScript If Else Statements. Learn how to use If Else in javascript and also JavaScript If Else Statements. if-else Statement in JavaScript. JavaScript's conditional statements: if; if-else; nested-if; if-else-if. These statements allow you to control the flow of your program's execution based upon conditions known only during run time.

Decision Making in programming is similar to decision making in real life. In programming also we face some situations where we want a certain block of code to be executed when some condition is fulfilled.
A programming language uses control statements to control the flow of execution of the program based on certain conditions. These are used to cause the flow of execution to advance and branch based on changes to the state of a program.

JavaScript’s conditional statements:

  • if
  • if-else
  • nested-if
  • if-else-if

These statements allow you to control the flow of your program’s execution based upon conditions known only during run time.

  • if: if statement is the most simple decision making statement. It is used to decide whether a certain statement or block of statements will be executed or not i.e if a certain condition is true then a block of statement is executed otherwise not.
    Syntax:
if(condition) 
{
   // Statements to execute if
   // condition is true
}

Here, condition after evaluation will be either true or false. if statement accepts boolean values – if the value is true then it will execute the block of statements under it.
If we do not provide the curly braces ‘{‘ and ‘}’ after if( condition ) then by default if statement will consider the immediate one statement to be inside its block. For example,

if(condition)
   statement1;
   statement2;

// Here if the condition is true, if block 
// will consider only statement1 to be inside 
// its block.

Flow chart:

Example:

<script type = "text/javaScript"> 

// JavaScript program to illustrate If statement 

var i = 10; 

if (i > 15) 
document.write("10 is less than 15"); 

// This statement will be executed 
// as if considers one statement by default 
document.write("I am Not in if"); 

< /script> 

Output:

I am Not in if
  • if-else: The if statement alone tells us that if a condition is true it will execute a block of statements and if the condition is false it won’t. But what if we want to do something else if the condition is false. Here comes the else statement. We can use the else statement with if statement to execute a block of code when the condition is false.
    Syntax:
if (condition)
{
    // Executes this block if
    // condition is true
}
else
{
    // Executes this block if
    // condition is false
}


Example:

<script type = "text/javaScript"> 

// JavaScript program to illustrate If-else statement 

var i = 10; 

if (i < 15) 
document.write("10 is less than 15"); 
else
document.write("I am Not in if"); 

< /script> 

Output:

i is smaller than 15
  • nested-if A nested if is an if statement that is the target of another if or else. Nested if statements means an if statement inside an if statement. Yes, JavaScript allows us to nest if statements within if statements. i.e, we can place an if statement inside another if statement.
    Syntax:
if (condition1) 
{
   // Executes when condition1 is true
   if (condition2) 
   {
      // Executes when condition2 is true
   }
}

Example:

<script type = "text/javaScript"> 

// JavaScript program to illustrate nested-if statement 

var i = 10; 

if (i == 10) { 

// First if statement 
if (i < 15) 
	document.write("i is smaller than 15"); 

// Nested - if statement 
// Will only be executed if statement above 
// it is true 
if (i < 12) 
	document.write("i is smaller than 12 too"); 
else
	document.write("i is greater than 15"); 
} 
< /script> 

Output:

i is smaller than 15
i is smaller than 12 too
  • if-else-if ladder Here, a user can decide among multiple options.The if statements are executed from the top down. As soon as one of the conditions controlling the if is true, the statement associated with that if is executed, and the rest of the ladder is bypassed. If none of the conditions is true, then the final else statement will be executed.
if (condition)
    statement;
else if (condition)
    statement;
.
.
else
    statement;


Example:

<script type = "text/javaScript"> 
// JavaScript program to illustrate nested-if statement 

var i = 20; 

if (i == 10) 
document.wrte("i is 10"); 
else if (i == 15) 
document.wrte("i is 15"); 
else if (i == 20) 
document.wrte("i is 20"); 
else
document.wrte("i is not present"); 
< /script> 

Output:

i is 20

How to Retrieve full Profile of LinkedIn User using Javascript

How to Retrieve full Profile of LinkedIn User using Javascript

I am trying to retrieve the full profile (especially job history and educational qualifications) of a linkedin user via the Javascript (Fetch LinkedIn Data Using JavaScript)

Here we are fetching LinkedIn data like Username, Email and other fields using JavaScript SDK.

Here we have 2 workarounds.

  1. Configuration of linkedIn developer api
  2. Javascript Code to fetch records

Configuration of linkedIn developer api

In order to fetch records, first we need to create developer api in linkedin which will act as token/identity while fetching data from other linkedin accounts.

So to create api, navigate to https://linkedin.com/developer/apps and click on 'Create Application'.

After navigating, fill in details like name, description and other required fields and then submit.

As we submit, it will create Client ID and Client Secret shown below, which we will be using in our code while communicating to fetch records from other LinkedIn account.

Note: We need to provide localhost Url here under Oauth 2.0. I am using my localhost, but you can probably use other production URLs under Oauth 2.0 where your app is configured. It will make your api  consider the Url as trusted which fetching records.

Javascript Code to fetch records

For getting user details like first name, last name,User image can be written as,

<script type="text/javascript" src="https://platform.linkedin.com/in.js">  
    api_key: XXXXXXX //Client ID  
    onLoad: OnLinkedInFrameworkLoad //Method that will be called on page load  
    authorize: true  
</script>  
<script type="text/javascript">  
    function OnLinkedInFrameworkLoad() {  
        IN.Event.on(IN, "auth", OnLinkedInAuth);  
    }  
  
    function OnLinkedInAuth() {  
        IN.API.Profile("me").result(ShowProfileData);  
    }  
  
    function ShowProfileData(profiles) {  
        var member = profiles.values[0];  
        var id = member.id;  
        var firstName = member.firstName;  
        var lastName = member.lastName;  
        var photo = member.pictureUrl;  
        var headline = member.headline;  
        //use information captured above  
        var stringToBind = "<p>First Name: " + firstName + " <p/><p> Last Name: " + lastName + "<p/><p>User ID: " + id + " and Head Line Provided: " + headline + "<p/>"  
        document.getElementById('profiles').innerHTML = stringToBind;  
    }  
</script>    

Kindly note we need to include 'https://platform.linkedin.com/in.js' as src under script type as it will act on this Javascript SDK provided by Linkedin.

In the same way we can also fetch records of any organization with the companyid as keyword.

<head>  
    <script type="text/javascript" src="https://platform.linkedin.com/in.js">  
        api_key: XXXXXXX ////Client ID  
        onLoad: onLinkedInLoad  
        authorize: true  
    </script>  
</head>  
  
<body>  
    <div id="displayUpdates"></div>  
    <script type="text/javascript">  
        function onLinkedInLoad() {  
            IN.Event.on(IN, "auth", onLinkedInAuth);  
            console.log("On auth");  
        }  
  
        function onLinkedInAuth() {  
            var cpnyID = XXXXX; //the Company ID for which we want updates  
            IN.API.Raw("/companies/" + cpnyID + "/updates?event-type=status-update&start=0&count=10&format=json").result(displayCompanyUpdates);  
            console.log("After auth");  
        }  
  
        function displayCompanyUpdates(result) {  
            var div = document.getElementById("displayUpdates");  
            var el = "<ul>";  
            var resValues = result.values;  
            for (var i in resValues) {  
                var share = resValues[i].updateContent.companyStatusUpdate.share;  
                var isContent = share.content;  
                var isTitled = isContent,  
                    isLinked = isContent,  
                    isDescription = isContent,  
                    isThumbnail = isContent,  
                    isComment = isContent;  
                if (isTitled) {  
                    var title = isContent.title;  
                } else {  
                    var title = "News headline";  
                }  
                var comment = share.comment;  
                if (isLinked) {  
                    var link = isContent.shortenedUrl;  
                } else {  
                    var link = "#";  
                }  
                if (isDescription) {  
                    var description = isContent.description;  
                } else {  
                    var description = "No description";  
                }  
                /* 
                if (isThumbnailz) { 
                var thumbnailUrl = isContent.thumbnailUrl; 
                } else { 
                var thumbnailUrl = "http://placehold.it/60x60"; 
                } 
                */  
                if (share) {  
                    var content = "<a target='_blank' href=" + link + ">" + comment + "</a><br>";  
                    //el += "<li><img src='" + thumbnailUrl + "' alt=''>" + content + "</li>";  
                    el += "<li><div>" + content + "</div></li>";  
                }  
                console.log(share);  
            }  
            el += "</ul>";  
            document.getElementById("displayUpdates").innerHTML = el;  
        }  
    </script>  
</body>  

We can get multiple metadata while fetching records for any any organization. We can get company updates as shown below.

Conclusion

We can also fetch any company specific data like company job updates/post, total likes, comments, and number of views along with a lot of metadata we can fetch which I have shown below.

Thank you for reading !

Making a Game in VueJS using Vuex | VueJS Tutorial

Making a Game in VueJS using Vuex | VueJS Tutorial

Today we create a Game in VueJS using Vuex to manage our state. This is an open source community driven game and I would love for you to get involved. We explore the game loop, upgrades, levelling and much more

Today we create a Game in VueJS using Vuex to manage our state. This is an open source community driven game and I would love for you to get involved. We explore the game loop, upgrades, levelling and much more. We looking into VueJS lifecycle methods as well as Vuex mutations, getters and state.

A Javascript Project

Day 15 #31Days31Videos