Tuesday, March 8, 2016

Bubble graph - d3.js

This is the bubble graph which I wrote myself for the WSO2ConAsia 2016 twitter analytic dashboard, in a situation where there is no one particular graph which fulfilled all the necessary requirements at the wso2 conference.

Some of the requirements that fulfilled through this bubble graph are
  • Dynamic generation of Bubbles according to the input variables(Trending Topics).
  • Having a dynamic legend.
  • Having two independent labels one under the other.(Topic and the count).
The inputs for the graph is taken from a table in a database which has 3 columns (Topic, Count, Color).

An ajax call is sent to get data and all rendering done via d3.js standard library. The javascript libraries that should import are "jquery.min.js","bootstrap.min.js" and "d3.min.js".

The bellow code will help you to understand the how to write the bubble graph using pure d3.



 /**********************************************************************************************************  
  * Bubble Graph   
  **********************************************************************/  
 var authenticatingString = window.btoa("admin:admin");  
 function drawBubbleGraph(Bubblediv) {  
   var divID = "#" + Bubblediv;  
   var Nodes = [];  
   var dataN = [];  
   var width = $(divID).width();  
   var height = $(divID).height();  
 /*  
 *Here the ajax call is sent to WSO2 DAS analytic tables, Instead of this you can use ajax calls to mysql database to recieve data from its tables(GET or POST)  
 */  
   var bubble = "https://lcalhost:9446/analytics/tables/BUBBLE";  
   $.when(  
     $.ajax({  
       url: bubble,  
       beforeSend: function(xhr) {  
         xhr.setRequestHeader("Authorization", "Basic " + authenticatingString);  
       },  
       method: "GET",  
       contentType: "application/json",  
       success: function(data) {  
         dataN = data;  
       }  
     })  
   ).then(function() {  
     drawBubble(dataN);  
   });  
   function drawBubble(dataN1) {  
     for (var i = 0; i < dataN1.length; i++) { //  
       var d = dataN1[i].values;  
       Nodes.push(d);  
     }  
     d3.select("svg").remove();  
 //*append a svg of hight and width of the div ,to the div   
     var svg = d3.select(divID).append('svg')  
       .attr('width', width)  
       .attr('height', height);  
     var bubble = d3.layout.pack()  
       .size([width, height])  
       .value(function(d) {  
         return d.size;  
       })  
       .padding(3);  
     // generate data with calculated layout values  
     var nodes = bubble.nodes(processData(Nodes))  
       .filter(function(d) {  
         return !d.children;  
       }); // filter out the outer bubble  
 //nodes for Bubbles are generated and a circle is appended.  
     var node = svg.selectAll('circle')  
       .data(nodes);  
     node.append("title")  
       .text(function(d) {  
         return d.name;  
       });  
     node.enter().append('circle')  
       .attr('transform', function(d) {  
         return 'translate(' + d.x + ',' + d.y + ')';  
       })  
       .attr('r', function(d) {  
         return d.r;  
       }) //(d.size *2); })  
       .attr('fill', function(d) {  
         return d.color;  
       })  
       .style("fill-opacity", 0.7)  
       .style("stroke",function (d) {  
             return d.color;  
        });  
 //Label of the name on the bubble  
     var label = node.enter().append("text")  
       .style("font-family", "sans-serif")  
       .style("text-anchor", "middle")  
       .style("font-size", function(d) {  
           return d.r/4 ;  
       })  
       .style("fill","#000000")  
       .text(function(d) {  
           return d.name ;  
       })  
       .attr('transform', function(d) {  
         return 'translate(' + d.x + ',' + d.y + ')';  
       });  
 //label of the count attach below the name  
         var label2 = node.enter().append("text")  
             .style("font-family", "sans-serif")  
             .style("text-anchor", "middle")  
             .style("font-size", function(d) {  
                 return d.r/2;  
             })  
             .style("fill","#000000")  
             .text(function(d) {  
                 return d.size;  
             })  
             .attr('transform', function(d) {  
                 d.y=d.y+d.r/2;  
               return 'translate(' + d.x + ',' + d.y + ')';  
             });  
     var legendRectSize = 20,  
       legendSpacing = 5;  
  //The legend is append to the svg  
  var legend = d3.select('svg')  
       .selectAll("svg")  
       .data(nodes)  
       .enter()  
       .append('g')  
       .attr('class', 'legend')  
       .attr('transform', function(d, i) {  
         var height = legendRectSize +5;  
         var x = 10;  
         var y =10+( i * height);  
         return 'translate(' + x + ',' + (y) + ')';  
       });  
     legend.append('rect')  
       .attr('width', legendRectSize)  
       .attr('height', legendRectSize)  
       .attr('padding', 2)  
       .style('fill', function(d) {  
                 return d.color;  
       })  
       .style('stroke', function(d) {  
                 return d.color;  
       });  
     legend.append('text')  
       .attr('x', legendRectSize + legendSpacing)  
       .attr('y', legendRectSize - legendSpacing)  
       .text(function(d) {  
         return d.name;  
       });  
 /*  
 *The data is organized as name,color,size  
 */  
     function processData(data) {  
       var obj = data;  
       var newDataSet = [];  
       for (var prop in obj) {  
         if(obj[prop].degree>0){  
         newDataSet.push({  
           name: obj[prop].name,  
           color: obj[prop].color,  
           size: obj[prop].degree  
         });  
         }  
       }  
       return {  
         children: newDataSet  
       };  
     }  
   }  
 }  


 Hope you enjoyed reading my fancy bubble graph post. Please leave comments on my technical blog.

For further more details you can drop a mail to me: gdrdabarera@gmail.com

No comments:

Post a Comment