Does having 11 payment methods put you in the top 10% or somewhere around the middle? It felt like a great chance to develop a new comparison paradigm that put relative performance at the fore, in an intuitive way.
Thankfully, we had recently seen a fantastic example that inspired us from The Pudding, so we had a picture in our mind of how this could behave. But how did we build it? This post charts our progress through developing this feature and coming out with a pretty nice (we think) result.
TL;DR: after quite a lot of fiddling and testing, we produced this interactive & responsive chart, which satisfied both us and the client to the tune of around 100 hours front end development & testing time.
We choose a D3 library from the many chart plugins available because it offers the flexibility to customize and visualize as per requirement,
While most of the libraries are free and open source, some of them provide a paid version with additional features. For example, Highcharts is free for personal use, but you need to purchase a license for commercial usage. D3 is an open-source library, so it enables users to work with the source code and add specific features.
There are many libraries that render charts using HTML/CSS with SVG or CANVAS technology and come with various customization options, such as Highcharts, amCharts, Google Chart, CanvasJS, and jqChart.
However, some of them are paid for while others don't provide the required functionality, such as preventing elements overlapping and causing elements to be attracted towards a specified position. In D3 library, the force-directed algorithm balances the node positions with the fewest iterations.
To summarize, the following advantages of the D3 library helped us to build the chart we wanted:
We used D3.js library to achieve our goal, taking advantage of its various modules (Arrays, Axes, Forces, Scales, Selections, Transitions etc).
We also extended D3’s source code to meet our own needs.
Our example shows a visualization of gambling operators sorted by a specific parameter (e.g. Wagering (bonus), Wagering (deposit), Bonus cap (£), Bonus %, Software Providers, Deposit Methods, Withdrawal Methods).
The chart has the following interactive features:
The process was to implement several points step by step:
Using D3.js we can manipulate with the Document Object Model (DOM). The D3 library provides numerous methods for transforming nodes: setting attributes or styles, registering event listeners, adding, removing or sorting nodes, and changing HTML or text content.
To start with, D3.js loads data and binds it to DOM elements. D3 works with different types of files (css, tsv, json, xml etc). We chose a JSON file. D3.json() takes the JSON file as input and converts it into an array of objects. It uses the data() method and adds enter() method, which works kind of like a loop, then append() method which adds elements to the DOM.
var circles = self.chart
.append("div")
.attr("class", "casino-circles")
.data(filteredNodes)
.enter()
.append("div")
.attr("class", "casino-circle")
.attr("data-id", function(d) {
return "casino-" + d.id;
})
One of the complex issues we had to overcome was the fact that the one chart comprised several different graphs with their own measurements, axis and data.
We had to be attentive when adding axes to the chart as we had to map a dimension of abstract data to a visual representation.
In other words, we need to take an abstract value of data (e.g. bonus cap in £) and return a visual value, such as the horizontal position of a dot in pixels.
Let’s say that our input data Bonus cap £ will be some number between 20 and 600; we need to scale our data down to fit into the chart viewport.
This is implemented by D3 scale functions.
They map an input domain ([20, 600]) to an output range (in our case chart width). The Domain() method defines full chart boundaries. First parameter points to the minimum value in the data, the second one to the maximum value in the data.
The Range() method will store our values inside our SVG container. This function is responsible for the physical boundaries of our chart. The first parameter gets value (0), the second one width/height of SVG container.
There were several difficult moments in the implementation. Some things were achieved by trial and error. In particular, force simulation.
From
And
To
The power and flexibility of the force simulation is centered around D3 force functions which adjust the position and velocity of elements to achieve a number of effects, such as attraction, repulsion and collision detection.
We used the forceCollide() function to prevent elements overlapping and forceX()/forceY() to cause elements to be attracted towards specified position(s).
To get a perfect result, we match values of forceX(), forceY() and forceCollide(). The number of iterations and strength parameters are also important in getting things to look how we want.
We also used a custom force to constrain the position of nodes within the rectangular bounds of the containing SVG element.
The nodes aren’t able to go outside these bounds; we update the node positions to be within the range [radius, width - radius] for x, [radius, height - radius] for y.
The chart is very flexible. It responds to any changes. The js code recalculates the width and height of the chart, operator, tooltips’ position, ticks and ranges.
The chart is recalibrated on:
In summary, the D3 library is a very powerful tool that allows you to apply data-driven transformations to the document. We hope you try it!