Treemap quick tutorial

This tutorial requires you to have read Feeding JSON tree structures to the JIT and on controllers first.

Hi, this is going to be a quick tutorial on how to set the treemap up and running.

Note: You could change all calls to TM.Squarified to TM.SliceAndDice and it should also work.

We are going to work with this tree JSON structure:

var json = {"id":"node02",
 "name":"0.2",
 "data":[
    {"key":"key1",
     "value":195},
    {"key":"key2",
     "value":5}],
 "children":[
    {"id":"node13",
     "name":"1.3",
     "data":[
        {"key":"key1",
         "value":23},
        {"key":"key2",
         "value":8}],
     "children":[
        {"id":"node24",
         "name":"2.4",
         "data":[
            {"key":"key1",
             "value":6},
            {"key":"key2",
             "value":-75}],
         "children":[]},
        {"id":"node25",
         "name":"2.5",
         "data":[
            {"key":"key1",
             "value":9},
            {"key":"key2",
             "value":-48}],
         "children":[]},
        {"id":"node26",
         "name":"2.6",
         "data":[
            {"key":"key1",
             "value":1},
            {"key":"key2",
             "value":-1}],
         "children":[]},
        {"id":"node27",
         "name":"2.7",
         "data":[
            {"key":"key1",
             "value":7},
            {"key":"key2",
             "value":25}],
         "children":[]}]},
    {"id":"node18",
     "name":"1.8",
     "data":[
        {"key":"key1",
         "value":17},
        {"key":"key2",
         "value":28}],
     "children":[
        {"id":"node29",
         "name":"2.9",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":-28}],
         "children":[]},
        {"id":"node210",
         "name":"2.10",
         "data":[
            {"key":"key1",
             "value":9},
            {"key":"key2",
             "value":-83}],
         "children":[]}]},
    {"id":"node111",
     "name":"1.11",
     "data":[
        {"key":"key1",
         "value":25},
        {"key":"key2",
         "value":-82}],
     "children":[
        {"id":"node212",
         "name":"2.12",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":-27}],
         "children":[]},
        {"id":"node213",
         "name":"2.13",
         "data":[
            {"key":"key1",
             "value":3},
            {"key":"key2",
             "value":-80}],
         "children":[]},
        {"id":"node214",
         "name":"2.14",
         "data":[
            {"key":"key1",
             "value":7},
            {"key":"key2",
             "value":-73}],
         "children":[]},
        {"id":"node215",
         "name":"2.15",
         "data":[
            {"key":"key1",
             "value":7},
            {"key":"key2",
             "value":26}],
         "children":[]}]},
    {"id":"node116",
     "name":"1.16",
     "data":[
        {"key":"key1",
         "value":17},
        {"key":"key2",
         "value":91}],
     "children":[
        {"id":"node217",
         "name":"2.17",
         "data":[
            {"key":"key1",
             "value":7},
            {"key":"key2",
             "value":48}],
         "children":[]},
        {"id":"node218",
         "name":"2.18",
         "data":[
            {"key":"key1",
             "value":10},
            {"key":"key2",
             "value":-86}],
         "children":[]}]},
    {"id":"node119",
     "name":"1.19",
     "data":[
        {"key":"key1",
         "value":52},
        {"key":"key2",
         "value":-77}],
     "children":[
        {"id":"node220",
         "name":"2.20",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":64}],
         "children":[]},
        {"id":"node221",
         "name":"2.21",
         "data":[
            {"key":"key1",
             "value":5},
            {"key":"key2",
             "value":84}],
         "children":[]},
        {"id":"node222",
         "name":"2.22",
         "data":[
            {"key":"key1",
             "value":6},
            {"key":"key2",
             "value":81}],
         "children":[]},
        {"id":"node223",
         "name":"2.23",
         "data":[
            {"key":"key1",
             "value":1},
            {"key":"key2",
             "value":25}],
         "children":[]},
        {"id":"node224",
         "name":"2.24",
         "data":[
            {"key":"key1",
             "value":4},
            {"key":"key2",
             "value":18}],
         "children":[]},
        {"id":"node225",
         "name":"2.25",
         "data":[
            {"key":"key1",
             "value":10},
            {"key":"key2",
             "value":37}],
         "children":[]},
        {"id":"node226",
         "name":"2.26",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":83}],
         "children":[]},
        {"id":"node227",
         "name":"2.27",
         "data":[
            {"key":"key1",
             "value":10},
            {"key":"key2",
             "value":-62}],
         "children":[]}]},
    {"id":"node128",
     "name":"1.28",
     "data":[
        {"key":"key1",
         "value":37},
        {"key":"key2",
         "value":-40}],
     "children":[
        {"id":"node229",
         "name":"2.29",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":-67}],
         "children":[]},
        {"id":"node230",
         "name":"2.30",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":46}],
         "children":[]},
        {"id":"node231",
         "name":"2.31",
         "data":[
            {"key":"key1",
             "value":4},
            {"key":"key2",
             "value":-99}],
         "children":[]},
        {"id":"node232",
         "name":"2.32",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":-38}],
         "children":[]},
        {"id":"node233",
         "name":"2.33",
         "data":[
            {"key":"key1",
             "value":1},
            {"key":"key2",
             "value":-3}],
         "children":[]},
        {"id":"node234",
         "name":"2.34",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":82}],
         "children":[]}]},
    {"id":"node135",
     "name":"1.35",
     "data":[
        {"key":"key1",
         "value":24},
        {"key":"key2",
         "value":63}],
     "children":[
        {"id":"node236",
         "name":"2.36",
         "data":[
            {"key":"key1",
             "value":10},
            {"key":"key2",
             "value":8}],
         "children":[]},
        {"id":"node237",
         "name":"2.37",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":63}],
         "children":[]},
        {"id":"node238",
         "name":"2.38",
         "data":[
            {"key":"key1",
             "value":6},
            {"key":"key2",
             "value":46}],
         "children":[]}]}]};

Note: remember that the Treemap takes the first dataset object value to calculate the rectangles dimension. That means that the values you setted on the first dataset object for all nodes must be coherent. Coherent means that, for example, if node A has nodes B and C as children, B having 3 as its first dataset object value and C having 2 as its first dataset value, then A must have 5 as its first dataset object value.

Put this HTML in your page:

<html>
	<head>

	<link type="text/css" rel="stylesheet" href="/static/css/example-treemap.css" />

	<script type="text/javascript" src="/static/js/mootools-beta-1.2b2.js"></script>
	<script type="text/javascript" src="/static/js/treemap/Treemap.js" ></script>
	<script type="text/javascript" src="/static/js/example/example-treemap.js" ></script>

	</head>

	<body onload="init();">

<div id="infovis" />

	</body>
</html>

Note: You’ll probably have to change the paths to the css and javascript files.
Note2: This is the only visualization that requires Mootools 1.2+ to run. I use version 1.2b2 and no, I haven’t tested it with Mootools 1.2b1, but I guess it should work. Download from here

Now, create a treemap-example.css and put this code in it:

html, body {
	width:100%;
	height:100%;
	background-color:#222;
	text-align:center;
	overflow:hidden;
	font-size:10px;
	font-family:Verdana, Geneva, Arial, Helvetica, sans-serif;
}

#infovis {
	position:relative;
	width:900px;
	height:500px;
	margin:auto;
	background-color:#1D1D20;
}

#infovis div {
	position:absolute;
	overflow:hidden;
}

#infovis .content {
	background-color:#333;
	border:0px solid #111;
}

#infovis .head {
	height:12px;
	color:white;
	background-color:#444;
}

#infovis .head.in-path {
	background-color:#655;
}

#infovis .body {
	background-color:black;
}

#infovis .leaf {
	color:white;
	background-color:#111;
	display:table-cell;
	vertical-align:middle;
}

#infovis .over-leaf {
	border:1px solid #9FD4FF;
}

#infovis .over-content {
	background-color: #9FD4FF;
}

#infovis .over-head { /* ...boy i'm funny */
	background-color:#A4D9FF;
	color:black;
}

/*TOOLTIPS*/
.tool-tip {
	color: #fff;
	width: 139px;
	z-index: 13000;
	background-color: black;
}

.tip-title {
	font-weight: bold;
	font-size: 11px;
	margin: 0;
	color: #9FD4FF;
	padding: 8px 8px 4px;
	background-color: black;
}

.tip-text {
	font-size: 11px;
	padding: 4px 8px 8px;
	background-color: black;
}

Note: I won’t explain all CSS classes, they are pretty much self explainable. However, you must put a position:relative; in the infovis container (the visualization container), just as specified on the CSS stylesheet.

Finally, create an example-treemap.js file and put this code in it:

function init() {
	var json = //json data specified above...
	var tm = new TM.Squarified();
	tm.loadFromJSON(json);

}

You should see a treemap up and running.

Some notes:

  • It’s mandatory to put the width and height style properties on the main div container, just as specified on the CSS stylesheet.
  • You could change the main container id by setting the Config.rootId property to whatever id you like. Be sure to set that property before making a TM instance.

Customizing the Treemap

Let’s add some colors!
In order to add colors you must know three things:

  • Colors are calculated by taking the second dataset object value. You must also know the range of this value. In this example the second value ranges between [-100, 100]. You can change these values by setting the Config.Color.minValue and Config.Color.maxValue parameters. Remember to do this before instanciating the TM.
  • You can also choose the color range for your visualization, this is done by setting the Config.Color.minColorValue and Config.Color.maxColorValue parameters. These properties take an array of 3 integers each describing an RGB value. Remember to do this before instanciating the TM.
  • Finally, to enable treemap coloring you must set the property Config.Color.allow to true.

So the init javascript function would now look like:

function init() {
	var json = //..json data
	//Allow coloring
	Config.Color.allow = true;
//Set min value and max value for the second *dataset* object values.
//Default's to -100 and 100.
	Config.Color.minValue = -100;
	Config.Color.maxValue = 100;
//Set color range. Default's to reddish and greenish. It takes an array of three
//integers as R, G and B values.
	Config.Color.minColorValue = [255, 0, 50];
	Config.Color.maxColorValue = [0, 255, 50];

	var tm = new TM.Squarified();
	tm.loadFromJSON(json);
}

You should see a colored treemap now.

Finally, let’s put nice tooltips! We’ll do this by using the Tooltip Mootools class.
First, we’ll define a controller to put the event handlers we need on element creation. The element is here the reactangle created.
I also define some extra methods that convert the dataset to HTML.
I also allow tooltips by setting Config.tips to true.

So the JavaScript file should now look like this:

function init() {
	var json = //...same json data as before...
	//Allow coloring
	Config.Color.allow = true;
//Set min value and max value for the second *dataset* object values.
//Default's to -100 and 100.
	Config.Color.minValue = -100;
	Config.Color.maxValue = 100;
//Set color range. Default's to reddish and greenish. It takes an array of three
//integers as R, G and B values.
	Config.Color.minColorValue = [255, 0, 50];
	Config.Color.maxColorValue = [0, 255, 50];

	//Allow tips for treemap
	Config.tips = true;

	var tm = new TM.Squarified({
//The interface method to be called, treemap element creation.
		onCreateElement: function(domElement, node) {
			this.makeTip(domElement, node);
		},
//Tooltip content is setted by setting the *title* of the element to be *tooltiped*.
//Read the mootools docs for further understanding.
		makeTip: function(elem, json) {
			var title = json.name;
			var html = this.makeHTMLFromData(json.data);
			elem.set('title', title + '::' + html);
		},
//Take each dataset object key and value and make an HTML from it.
		makeHTMLFromData: function(data) {
			var html = '';
			for(var i=0; i<data.length; i++) {
				html += data[i].key + ': ' + data[i].value + '<br />';
			}
			return html;
		}

	});

	tm.loadFromJSON(json);
}

You should see some tooltips now!

Remember that you have more controller methods to customize your visualization just as you want! Hope it was helpful.

4 Responses to “Treemap quick tutorial”


  1. 1 Benjamin Goldenberg

    I was wondering if there is a practical limit to the number of elements in the treemap. I am looking at generating a Treemap with about 5000 nodes. About 70 are top level. The JSON string ends up being huge, about 800k, without any compression. Will the treemap be able to handle this size tree?

    Thanks,
    Ben

  2. 2 Nicolas Garcia Belmonte

    Hi Benjamin,
    I think that the top feed for a treemap is 600 nodes (aprox.). However, you can set a controller to your treemap that allows it to bufferize nodes. That means that even when having a larger tree, you can force the TM to display only N levels below the actual root. As you traverse the tree, it will make requests for new nodes to be displayed while deleting unnecesary nodes and thus keeping a smaller number of nodes in memory. If you want to know more you can check the on controllers post and the example source for the Spacetree (packaged in the library). Hope this helps

  3. 3 Benjamin Goldenberg

    Thanks for the advice, Nicolas. I’m still having some trouble figuring it out. It doesn’t help that I don’t have much JavaScript experience. I looked at the controller post. In order to ‘bufferize nodes’, should I implement the request function to only call onComplete() when the level is less than N? Should we continue this conversation on the Google Group? Thanks for your help.

  4. 4 Nicolas Garcia Belmonte

    Yes we should, I’ll post your question there: http://groups.google.com/group/javascript-information-visualization-toolkit

Comments are currently closed.