Leonardo Da Codinchi Leonardo Da Codinchi - 14 days ago 4x
jQuery Question

Draw rect according to json array?

I find d3js very interesting.So I thought may be I should give it a shot.I am fairly new to this framework and need some assistance
I have a json file.This is how it goes--:

["2511a51", [["mumbai",1,6], ["Baroda",2,7]]]
["2882bd9", [["mumbai",3,8], ["chennai", 2,9]]]
["1d3e1a2", [["mumbai",0,3],["Baroda",2,6], ["Delhi",7,1]]]
["1882b41", [["mumbai",10,9]]]
["1d4ffd8", [["chennai",2,5], ["mumbai", 5,9], ["Delhi",8,8]]]


  • 2511a51 is session id(ignore)

  • Mumbai,baroda,chennai and delhi !!! are indian cities.

  • Mumbai=draw red rectangle, baroda=brown rectangle ,chennai=green rectangle,delhi=blue rectangle

What I want is,if a json row has a and b -->then their respective colored rectangle should be drawn keeping c and d empty.So for this entire array,I get the below output.
As the image goes,

  • 5 session id`s means 5 rows.

  • first and second rows includes two rectangles,third and fifth row have 3 rectangle and 4th row have 1 rectangle with every city having their respective colour and column

  • Based on second value(ex.1 and 6 for 1st row)-->their colour intensity will be depended!!!more the number,darker the colour!!!

I want to code my javascript in such a way that I get this---:
Outout of array!!!

MY fiddle--not working

My code:

<!DOCTYPE html>

<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
var SVG = d3.select("body").append("svg")
.style("background-color", "beige")

var array= ["2511a51", [["a",1], ["b",2]]]
["2882bd9", [["a",3], ["c", 2]]]
["1d3e1a2", [["a",0],["b",2], ["d",7]]]
["1882b41", [["a",10]]]
["1d4ffd8", [["c",2], ["b", 5], ["d",8]]]

var RECT= SVG.selectAll("rect")
.attr("width", 30)
.attr("height", 10)
.style("fill","red");//how do I provide conditions for fill-->a=red,b=brown,c=green,d=blue
//how do I manage them such that they are arranged in a manner shown in the image.
//I am unable to move ahead of this!!!!I am facing problem in iterations and conditions


If possible,please give a small working sample!!!


UPDATE 2 : every time you are working with selects in d3 you are mapping data to your UI elements and their properties. in most of the cases you are doing it this way

 ... select('rect').data(myData)

then you need to actually map properties of items in your data set to the properties of UI elements, you are doing it providing functions which do the mapping , ie

  var myData = [{x:0, y:0 } , { x: 100 , y : 100 }]
  // we mapped our data to rect elements on svg canvas 
  // and created new rect elements for data items which didnt have it before
  // now we have two elements in total as myData had 2 elements
  var rect = svg.select('rect').data(myData).enter()

  // now each rect has x attribute equals to 'x' property of data item
  rect.attr('x', function(d) { return d.x } )

  // and the same for y attribute and 'y' property
  rect.attr('y', function(d) { return d.y } )

  // now if you also set height and width properties of UI elements 
  // you will see two rectangulars
  rect.attr('width', 50).attr('height', 50)

  // now you can rewrite your previos lines like that
  var xScale = function(d) { return d.x }
  rect.attr('x', xScale)

And now it is clear that if you have more complicated way of figuring out your X coordinate on the canvas than just your data item property, you will have more complicated function than current xScale

Now recalling school course of geometry we can do transformation from one scale to another , for instance

  var xScale = function(d) { return 50 + d.x * 100 } 

which means that if d.x equals to 1 , function will return 150 , for 2 it would be 250 etc

And last step , in order to avoid figuring out on your own how to create this scale function ,you can use built in d3 features , links to which I put in the end of the answer, for instance

   var xScale = d3.scale.linear()
           .domain([0, 10]).range([50, 550])    

UPDATED: fiddle - http://jsfiddle.net/EdjbH/5/

NOTES: I slightly changed your source data in order for it to make more sense to d3. Take a look at how color is generated, you will need to build your own palete as for instance gines capote recomended. In order to draw axises you can use d3 built in functions.

You need to do 3 things

  • to create x-axis and y-axis scales based on your domain

  • add .attr('x', function(d){ return xAxis(d[0]) }) and .attr('y', function(d){ return yAxis(d[1]) }) to your code generating RECT

  • fill also accept function , and it make sense to create scale to use here as well, would be something like .style('fill', function(d) { return colorScale(d[0]]) })

Also because in fact you have array of array you need to change .data(data) to .data(function(d){ return d[1] })

Alternatively you can code you scales by hand like

var svg = d3.select("svg")
        .style("background-color", "beige");

var data=  [{ key :"2511a51", values : [["a",1], ["b",2]] },
         { key :"2882bd9", values : [["a",3], ["c", 2]]},
         { key: "1d3e1a2", values : [["a",0],["b",2], ["d",7]] },
         { key :"1882b41", values : [["a",10]] },
         { key :"1d4ffd8", values : [["c",2], ["b", 5], ["d",8]]}];

var width  = 30, padding = 10, height = 10  

var   code = function (c) {return c.charCodeAt(0) - 'a'.charCodeAt(0) }
, xScale = function (d) { return (width + 2*padding) * code(d[0]) }
, yScale = function (d) { return (height + 2 * padding) * d[1] }            
, color = d3.scale.category20() // replace with your palete
, cScale = function(d) { return color(code(d[0])) }

var g = svg.selectAll("g").data(data).enter().append("g")

var rects= g.selectAll("rect.colored")
        .data(function(d){ return d.values })
        .attr("width", width)
        .attr("height", height)
        .attr('x', xScale )
        .attr('y', yScale )
        .style('fill',  cScale);

check this references