Creating Composite Node of a Graph using D3.js
Tags: javascript, html, css, webdev
Published: 2020-05-04 12:00:54

Lately I have been using D3 for visualizing data for a React project and it got my attention for a while. I was especially interested as to the scope of this very powerful tool that has a great problem solving ability range related to any kind of data visualization.
It gives you a feeling that you can do __ANYTHING__. Okay, lets talk about it.

### What is D3.js ?
D3.js is a javascript library used for visualizing data. It is very powerful with the combination of __SVG__ (Support Vector Graphics) and __HTML__.
Now it depends on the creativity of the developer using it to actually visualize it in the most beautiful way. 

Since this is data driven , d3.js works on your pure data and transforms it in a graphical way. While applying d3.js, you will doing lot of CSS, at the same time solving some Mathematical Coordinate Geometry problems. For instance, applying Pythagorean theorem, finding distance between two coordinates `(x1, y1)` and `(x2, y2)` on a graph etc.

This article especially focuses on creating a complex node of a graph. A Complex node refers to a node which will have a lot of elements or information attached to it, instead of just an empty circle.

### Why v5 version especially ?
You will find so many example snippets and gists especially on [bl.ocks.org](https://bl.ocks.org/) or [stackoverflow](https://stackoverflow.com/) for creating graphs or trees with `v3` version but not many on the `v5` version.

### Pre-requisite
Html, CSS , Javascript, Coordinate Geometry.

*Let's Start*

We will be writing a simple working script for creating a complex SVG node of a graph.
First, you need to include the following `<script>` inside your html `<body>` for using d3 `v5` library.
{% gist https://gist.github.com/afrinc/cef6f9842f2db6bfda98f83cff0b8047 %}


### Canvas and data container element
Specify the canvas’s `width` and `height` where all the SVG elements will reside. We then call `d3.select()` on `body` element, appending `svg` to it, and specifying properties like `width` and `height` We currently have our json data as `nodes` with all params that we require to visualize.

{% gist https://gist.github.com/afrinc/5f914b02fc8774e30adda7ad6f0dce97 %}

Lets append new element `g` into `svg` variable (canvas) and insert node data into it, indexing with `id`.

{% gist https://gist.github.com/afrinc/1cdb359989a266db497c2dc24f11b928 %}


### Rectangular node
Now we append `rect` element into our `svg` with `(x,y)` coordinates as `(0,0)`.

{% gist https://gist.github.com/afrinc/c039d9440761cd34e170fa9bbbc6b2c9 %}

Now this gets tricky here, as we now have our basic node ready and would like to place many more elements inside with reference to the rectangular node and not canvas. One of the ways for doing that is to get coordinates using `getBBox()`.

{% gist https://gist.github.com/afrinc/4ef3e69dbf02467b4e066ee9e4fd6ce7 %}


### Image element
Now that we have placement coordinates of this box, lets place things inside.
Say I want to place a logo ![image-icon](https://img.icons8.com/ios-glyphs/30/000000/superman.png) here available. It's simple.

{% gist https://gist.github.com/afrinc/b7a2de2184bafc941513d7a5c4403737 %}

As you can see we have tweaked `X` and `Y` a little bit depending on where we would like it to be. I wanted it to be in middle, with a little bit of tab  (`10`) from left.


### Text element
Now, we want some text. We use the node data and access it using keys. And again, append `text` to `svg` like below:

{% gist https://gist.github.com/afrinc/fba7870aeac966ac801c7248371bd0f5 %}

another example to add text

{% gist https://gist.github.com/afrinc/f6609a4b8efb110b1d4749c23601419b %}


### Circular counter element
Now what if I want to insert a circle inside the rectangular node and maintain a text inside it. We do it as follows:

{% gist https://gist.github.com/afrinc/3fe50772a8923b42b984778e75ac95e8 %}

and text

{% gist https://gist.github.com/afrinc/7d62cc15f4168799dcf8d1908864344b %}

At last simply merge all the elements into one.

{% gist https://gist.github.com/afrinc/41fff7583252dbc95023b76608b97256 %}

Wondering how does it look like while inspecting. See for yourself.

![inspect_element](https://user-images.githubusercontent.com/11709991/80964993-6fe35d00-8e2f-11ea-945c-9d28470331e8.PNG)