Creating interactive infographics with plain Javascript (Part-one)

Interactive infographics with plain Javascript

Introduction

Today’s browsers let us connect information in ways never seen before. Infographics is one such area. As a pictogram, it is an excellent visualisation tool. As an interactive webpage, you can achieve a new level of engagement with just a little bit of coding.

Many open-source libraries render fantastic infographics. Our favourites are D3, and vis.js. However, there are other times when we needed features that aren’t available from public libraries.

Objective

Let’s build an interactive infographic with plain Javascript.

Case Study

The Google Cloud Platform (GCP) is like a candy store to a web developer. Its product categories are more than fingers can count and each interconnects in different ways to solve complex problems.

The GCP “Org chart”. Official source: Google Cloud Platform

If we harness the power of a modern browser to showcase the benefits of GCP products, how would the UI look like? Is it possible to use basic Javascript techniques to produce extraordinary results?

Design approach

Our design approach is based on the idea of using a consistent and persistent User Interface (UI) to tell an engaging story. Let’s rethink design in two areas:

UI concept: the looking-glass

Getting started — the basic building blocks

Let’s introduce the notion of nodes and links as the basic building blocks of our design workflow.

Nodes are the start and end points. For example, a bus stop can be called a node. A bus route from one node to another can be called a link. A group of related nodes and links can be called a branch.

Basic building blocks : each node describes a set of unique relationships

Node elements. We can use an HTML element and a unique id to describe a node. For example, node11 would be node #1 of branch #1. Similarly, node12 would be node #2 of branch #1. In the above diagram, that would be circle “1” and “2”. The bus route #1 (i.e. branch #1) would connect circle “1” and “2”, as well as other circles (i.e. 2a,3,3a,3b).

Let’s use the style attribute to describe the unique position, shape and behaviour of each element. You can use any HTML, CSS, icons or images to represent a node or link. The circular nodes in our videos are simply div tags with a CSS border-radius.

<div id=”node11" style=”…”>1–1 Occupation Name</div><div id=”node12" style=”…”>1–2 Occupation Name</div>

Link elements. Links connects nodes. For example, link1112 connects node11 and node12.

<div style=”...” id=”link1112"></div>

Tip: Use an image overlay to guide your CSS positioning of the HTML elements.

Concept aside — how interaction works on a webpage

The nodes and links we’ve discussed are essentially DOM elements at browser runtime. The DOM, or Document Object Model, is a tree-like data structure for representing HTML elements and mapping content onto a physical display.

Conversely, we can also interact with any display elements by manipulating the DOM. In our project, we would like these nodes and links to respond to a specific user action such as a mouseover event.

document.addEventListener( "mouseover", myCustomFunction );

We’ll use this Javascript API to detect user actions and trigger a whole range of functionalities to create interactive web pages.

Creating workflow shortcuts

Let’s bind the node and link elements to its event listeners within a loop in two steps:

Step one. Assign the model (data).

Store your HTML element’s unique id values as an item[] array.

var item = [‘11’,’12',’1112',‘21’,’22',’2122',...];

Each value in the item[] array will correspond to the unique id value of each node or link (e.g. 11 refers to node11; 1112 refers to link1112.). You can think of item[] as a master registry.

Next set up legend[] to hold an array of objects. Each object is a dataset that will correspond to a specific user action.

var legend = {'item11' : { "node" : ['11'], "links" : [] },'item12' : { "node" : ['11','12'], "links" : ['1112'], },...}

Let’s take a moment to consider the implication of the above schema. Not only have we created a system to store content, we have also created a graph relationship to describe data connections.

We’ve reduced tons of code; sped up the design workflow; and separated the view from the model (data). Let’s move on to build the view engine.

Tip: For dynamic content management, consider encoding your dataset as JSON and access them via a database. Also, use any tools to edit your dataset and HTML layouts.

Step two. Loop through each HTML element to associate event listeners programmatically.

while (item[i]) {itemElement[i] = "node".concat(item[i]);itemElementName[i] = document.getElementById( itemElement[i] );itemElementName[i].addEventListener( "mouseover", mouseOver );itemElementName[i].addEventListener( "mouseout", mouseOut );...i++;}

  1. while iterates through the id values of each DOM element registered at item[].
  2. “item”.concat(item[i]) reattaches any custom prefixes you may have (i.e. “node”) to match the actual id values.
  3. itemElementName[i] = document.getElementById( item[i] ) builds an array of DOM references.
  4. mouseover” and “mouseout” binds each DOM element to a user action.

Tip # 1: Mobile and touch devices have its own set of event listeners such as _touchstart_ and _touchmove_. Use them to create responsive designs.

Tip #2: Use the “passive” parameter on your touch or wheel event listeners to improve browser performance like so:

document.addEventListener('touchstart', onTouchStart, {passive: true});

Customising interactive behaviours with CSS

We can create custom functions mouseOver and mouseOut to apply CSS effects:

function mouseOver(event) {for (var i in legend[this.id]["node"]) {var currKey = "node".concat(legend[this.id]["node"][i]);document.getElementById(currKey).style.background = "grey";...}for (var i in legend[this.id]["link"]) {var currKey = "link".concat(legend[this.id]["link"][i]);document.getElementById(currKey).style.border = "1px solid#000";...}

}

In our example, the mouseOver function turns the background colour of the targeted node(s) grey.

Use the same idea on link elements. In our example, we changed the colour of links1112 from grey to solid black when a mouse pointer hovers over node12 (node11 and node12 also turn grey).

Next, “reset” the CSS behaviour as soon as the cursor exits the current DOM element (see bold).

function mouseOut() {for (var i in legend[this.id]["node"]) {var currKey = "node".concat(legend[this.id]["node"][i]);document.getElementById(currKey).style.background = "unset";...}

for (var i in legend[this.id]["link"]) {...}

}

Unlimited scaling with SVG

Our GCP infographics use SVG extensively to support high-def resolution for a zooming feature that’ll be implemented in the next part of our discussion.

To change the HTML/CSS circle 1, or node11, into a hexagonal SVG shape, simply wrap your SVG content within an HTML container (see bold).

<div id=”node11" style=”display:flex; align-items:center;"><svg><path d="...some paths"/></svg><div style="align-items:center; width:100%;">My Text Label</div></div>

Populating content

We added SVG to the model. Let’s see how a sample layout with GCP content looks so far.

Graph relationships and interacting with SVG content

Next Steps

We’ve devised a schema and a view engine as a foundation for our design workflow.

In the next part, we’ll add navigation capabilities to the UI.

Side note

This story is a 5-part series on creating interactive infographics with Javascript. We’ve handpicked what’s important so that you can get to the essential parts quickly and adapt them in your project. It does help that you have some knowledge of CSS and HTML. Non-relevant code blocks are glossed over.

All video illustrations are screen captured from a Chrome browser. While the demo is based on GCP, you can find applications in org charts, ecosystems, subway maps, flowcharts, progression trees, network topologies, and any graph diagrams.

Many thanks to Chuck Erickson and the Google Team for the wonderful GCP solutions icon and diagram pack.

Links to other parts

Part-one → You’re are here.

Part-two adds navigation features to browse content.

Part-three adds a dynamic mini-map to enhance navigation.

Part-four adds an inline UI to access layered content.

Part-five demonstrates why it is so easy to create UIs with a human touch.

If you enjoyed this story, you can find more at Pageii Studio.