Monthly Archive for May, 2008

Further work on JIT

I’m very happy with this first JavaScript Infovis Toolkit release, and I’m already working on fixing some known bugs and adding features for the next release of this library.
For the next step I’ll be focusing on fixing bugs, refactoring code, adding some features and improving the documentation.
Some of the things you’ll find in my TODO list are:

  • For RGraphs:
    • Add polar interpolation in animations.
    • Mantain Child ordering during transitions.
    • Change node diameters based on the first dataset object value.
    • Graph support (trees with cycles…)
  • For the ST:
    • Code refactoring.
    • Performance improvements (bind with the Animation object).
    • Support for IE.
  • For Hypertrees:
    • Bug fix (node diameters, multilevel display).
    • Graph support, (although it might be supporting Graph structures already).
  • Treemaps
    • Bug fix (mostly on computing rectangles dimensions).

Before adding some radical features (binding visualizations with real time mutable data, etc.) I really want to have a strong API, and in order to do that, I must do some research on my own.
Don’t forget you have some quick tutorials on the visualizations. Also, the Hypertree, ST, RGraph and Treemap have some object references. Finally, there’s a Google Group about the JIT here.

RGraph quick tutorial

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

Note: I’ll be using Mootools for this tutorial. However, this visualization can be used without the Mootools library. You can find a Mootools build in the extras folder of the library.

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

We are going to work with this tree JSON structure:

var json = {"id":"node02",
 "name":"0.2",
 "data":[
    {"key":"key1",
     "value":8},
    {"key":"key2",
     "value":-88}],
 "children":[
    {"id":"node13",
     "name":"1.3",
     "data":[
        {"key":"key1",
         "value":8},
        {"key":"key2",
         "value":74}],
     "children":[
        {"id":"node24",
         "name":"2.4",
         "data":[
            {"key":"key1",
             "value":10},
            {"key":"key2",
             "value":55}],
         "children":[]},
        {"id":"node25",
         "name":"2.5",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":67}],
         "children":[]},
        {"id":"node26",
         "name":"2.6",
         "data":[
            {"key":"key1",
             "value":5},
            {"key":"key2",
             "value":-50}],
         "children":[]},
        {"id":"node27",
         "name":"2.7",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":10}],
         "children":[]},
        {"id":"node28",
         "name":"2.8",
         "data":[
            {"key":"key1",
             "value":2},
            {"key":"key2",
             "value":-69}],
         "children":[]},
        {"id":"node29",
         "name":"2.9",
         "data":[
            {"key":"key1",
             "value":3},
            {"key":"key2",
             "value":98}],
         "children":[]},
        {"id":"node210",
         "name":"2.10",
         "data":[
            {"key":"key1",
             "value":6},
            {"key":"key2",
             "value":12}],
         "children":[]},
        {"id":"node211",
         "name":"2.11",
         "data":[
            {"key":"key1",
             "value":2},
            {"key":"key2",
             "value":-95}],
         "children":[]}]},
    {"id":"node112",
     "name":"1.12",
     "data":[
        {"key":"key1",
         "value":1},
        {"key":"key2",
         "value":96}],
     "children":[
        {"id":"node213",
         "name":"2.13",
         "data":[
            {"key":"key1",
             "value":6},
            {"key":"key2",
             "value":-58}],
         "children":[]},
        {"id":"node214",
         "name":"2.14",
         "data":[
            {"key":"key1",
             "value":9},
            {"key":"key2",
             "value":-42}],
         "children":[]},
        {"id":"node215",
         "name":"2.15",
         "data":[
            {"key":"key1",
             "value":10},
            {"key":"key2",
             "value":92}],
         "children":[]},
        {"id":"node216",
         "name":"2.16",
         "data":[
            {"key":"key1",
             "value":7},
            {"key":"key2",
             "value":-15}],
         "children":[]},
        {"id":"node217",
         "name":"2.17",
         "data":[
            {"key":"key1",
             "value":3},
            {"key":"key2",
             "value":29}],
         "children":[]},
        {"id":"node218",
         "name":"2.18",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":-59}],
         "children":[]},
        {"id":"node219",
         "name":"2.19",
         "data":[
            {"key":"key1",
             "value":3},
            {"key":"key2",
             "value":21}],
         "children":[]},
        {"id":"node220",
         "name":"2.20",
         "data":[
            {"key":"key1",
             "value":2},
            {"key":"key2",
             "value":78}],
         "children":[]}]},
    {"id":"node121",
     "name":"1.21",
     "data":[
        {"key":"key1",
         "value":3},
        {"key":"key2",
         "value":53}],
     "children":[
        {"id":"node222",
         "name":"2.22",
         "data":[
            {"key":"key1",
             "value":5},
            {"key":"key2",
             "value":10}],
         "children":[]},
        {"id":"node223",
         "name":"2.23",
         "data":[
            {"key":"key1",
             "value":10},
            {"key":"key2",
             "value":21}],
         "children":[]},
        {"id":"node224",
         "name":"2.24",
         "data":[
            {"key":"key1",
             "value":6},
            {"key":"key2",
             "value":-32}],
         "children":[]},
        {"id":"node225",
         "name":"2.25",
         "data":[
            {"key":"key1",
             "value":5},
            {"key":"key2",
             "value":-42}],
         "children":[]},
        {"id":"node226",
         "name":"2.26",
         "data":[
            {"key":"key1",
             "value":2},
            {"key":"key2",
             "value":75}],
         "children":[]},
        {"id":"node227",
         "name":"2.27",
         "data":[
            {"key":"key1",
             "value":1},
            {"key":"key2",
             "value":-74}],
         "children":[]},
        {"id":"node228",
         "name":"2.28",
         "data":[
            {"key":"key1",
             "value":2},
            {"key":"key2",
             "value":52}],
         "children":[]},
        {"id":"node229",
         "name":"2.29",
         "data":[
            {"key":"key1",
             "value":10},
            {"key":"key2",
             "value":-49}],
         "children":[]}]},
    {"id":"node130",
     "name":"1.30",
     "data":[
        {"key":"key1",
         "value":9},
        {"key":"key2",
         "value":-29}],
     "children":[
        {"id":"node231",
         "name":"2.31",
         "data":[
            {"key":"key1",
             "value":6},
            {"key":"key2",
             "value":-23}],
         "children":[]},
        {"id":"node232",
         "name":"2.32",
         "data":[
            {"key":"key1",
             "value":10},
            {"key":"key2",
             "value":19}],
         "children":[]},
        {"id":"node233",
         "name":"2.33",
         "data":[
            {"key":"key1",
             "value":1},
            {"key":"key2",
             "value":92}],
         "children":[]}]},
    {"id":"node134",
     "name":"1.34",
     "data":[
        {"key":"key1",
         "value":9},
        {"key":"key2",
         "value":71}],
     "children":[
        {"id":"node235",
         "name":"2.35",
         "data":[
            {"key":"key1",
             "value":5},
            {"key":"key2",
             "value":-65}],
         "children":[]}]},
    {"id":"node136",
     "name":"1.36",
     "data":[
        {"key":"key1",
         "value":3},
        {"key":"key2",
         "value":-11}],
     "children":[
        {"id":"node237",
         "name":"2.37",
         "data":[
            {"key":"key1",
             "value":6},
            {"key":"key2",
             "value":-85}],
         "children":[]},
        {"id":"node238",
         "name":"2.38",
         "data":[
            {"key":"key1",
             "value":3},
            {"key":"key2",
             "value":-13}],
         "children":[]},
        {"id":"node239",
         "name":"2.39",
         "data":[
            {"key":"key1",
             "value":1},
            {"key":"key2",
             "value":80}],
         "children":[]},
        {"id":"node240",
         "name":"2.40",
         "data":[
            {"key":"key1",
             "value":10},
            {"key":"key2",
             "value":-69}],
         "children":[]}]},
    {"id":"node141",
     "name":"1.41",
     "data":[
        {"key":"key1",
         "value":10},
        {"key":"key2",
         "value":-4}],
     "children":[
        {"id":"node242",
         "name":"2.42",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":-27}],
         "children":[]},
        {"id":"node243",
         "name":"2.43",
         "data":[
            {"key":"key1",
             "value":9},
            {"key":"key2",
             "value":-44}],
         "children":[]},
        {"id":"node244",
         "name":"2.44",
         "data":[
            {"key":"key1",
             "value":9},
            {"key":"key2",
             "value":24}],
         "children":[]},
        {"id":"node245",
         "name":"2.45",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":-66}],
         "children":[]}]}]};

Put this HTML in your page:

<html>
	<head>

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

	<!--[if IE]>
		<script type="text/javascript" src="/static/js/excanvas.js"></script>
	<![endif]-->
	<script type="text/javascript" src="/static/js/mootools-1.2.js" ></script>
	<script type="text/javascript" src="/static/js/rgraph/RGraph.js" ></script>
	<script type="text/javascript" src="/static/js/example/example-rgraph.js" ></script>

	</head>
	<body onload="init();">

         <div id="infovis"></div>

	</body>
</html>

Note: You’ll probably have to change the paths to the css and javascript files.

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

html,body {
	width:100%;
	height:100%;
	overflow:hidden;
	margin:0;padding:0;
	background-color:#333;
	text-align:center;
}

#infovis {
	width:900px;
	height:500px;
	background-color:#222;
}

.node {
	color: white;
	background-color:transparent;
	cursor:pointer;
	font-weight:bold;
	opacity:0.9;
	border:1px solid red;
}

.node:hover {
	cursor:pointer;
	color: #222;
	background-color:white;
	font-weight:bold;
	opacity:1;
}

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

function init() {
  //Set node interpolation to linear (can also be 'polar')
  Config.interpolation = "linear";
  //Set distance for concentric circles
  Config.levelDistance = 100;

  var json= //data defined previously

  //Create a new canvas instance.
  var canvas = new Canvas('mycanvas', {
    //Where to inject the canvas. Any div container will do.
    'injectInto':'infovis',
    //width and height for canvas. Default's to 200.
    'width': 900,
    'height':500,
    //Canvas styles
    'styles': {
        'fillStyle': '#ccddee',
        'strokeStyle': '#772277'
    },
    //Add a background canvas for plotting
    //concentric circles.
    'backgroundCanvas': {
        //Add Canvas styles for the bck canvas.
      'styles': {
            'fillStyle': '#444',
            'strokeStyle': '#444'
        },
        //Add the initialization and plotting functions.
        'impl': {
            'init': $empty,
            'plot': function(canvas, ctx) {
                var times = 6, d = Config.levelDistance;
                var pi2 = Math.PI*2;
                for(var i=1; i<=times; i++) {
                    ctx.beginPath();
                    ctx.arc(0, 0, i * d, 0, pi2, true);
                    ctx.stroke();
                    ctx.closePath();
                }
            }
        }
    }
 });

  var rgraph= new RGraph(canvas,  {
    //Add a controller to make the tree move on click.
    onCreateLabel: function(domElement, node) {
      var d = $(domElement);
      d.addEvents({
        'click': function() {
          rgraph.onClick(d.id);
        }
      });
    }
   });

    //load tree from tree data.
    rgraph.loadTreeFromJSON(json);
    //compute positions
    rgraph.compute();
    //make first plot
    rgraph.plot();

}

You should see a RGraph up and running. Click on the labels and the tree should move.

Some notes:

  • If you want to know more about how the Canvas class is implemented and what other canvas customizations can be done please check this post and the canvas object reference. To know more about what canvas styles can be configured please check this post.
  • By assigning false to the backgroundCanvas property you can strip off the concentric circles. The backgroundCanvas functions and styles can also be customized to plot whatever background you like.

Customizing the Graph

Let's add some labels!

First, strip off the border: 1px solid red; line from the .node class in your CSS file.
It should look like this:

.node {
	color: white;
	background-color:transparent;
	cursor:pointer;
	font-weight:bold;
	opacity:0.9;
}

Now we are going to add a javascript controller in order to put the name of the nodes into the labels. Since we only need to do this once, we'll use the onCreateLabel method. If you don't know what I'm talking about you should probably read the on controllers post first.

So the JavaScript file should look like this now:

function init() {
  //Set node interpolation to linear (can also be 'polar')
  Config.interpolation = "linear";
  //Set distance for concentric circles
  Config.levelDistance = 100;

  var json= //data defined previously

  //Create a new canvas instance.
  var canvas = new Canvas('mycanvas', {
    //Where to inject the canvas. Any div container will do.
    'injectInto':'infovis',
    //width and height for canvas. Default's to 200.
    'width': 900,
    'height':500,
    //Canvas styles
    'styles': {
        'fillStyle': '#ccddee',
        'strokeStyle': '#772277'
    },
    //Add a background canvas for plotting
    //concentric circles.
    'backgroundCanvas': {
        //Add Canvas styles for the bck canvas.
      'styles': {
            'fillStyle': '#444',
            'strokeStyle': '#444'
        },
        //Add the initialization and plotting functions.
        'impl': {
            'init': $empty,
            'plot': function(canvas, ctx) {
                var times = 6, d = Config.levelDistance;
                var pi2 = Math.PI*2;
                for(var i=1; i<=times; i++) {
                    ctx.beginPath();
                    ctx.arc(0, 0, i * d, 0, pi2, true);
                    ctx.stroke();
                    ctx.closePath();
                }
            }
        }
    }
 });

  var rgraph= new RGraph(canvas,  {
    //Add a controller to make the tree move on click.
    onCreateLabel: function(domElement, node) {
      var d = $(domElement);
      d.set('html', node.name).addEvents({
        'click': function() {
          rgraph.onClick(d.id);
        }
      });
    }
   });

    //load tree from tree data.
    rgraph.loadTreeFromJSON(json);
    //compute positions
    rgraph.compute();
    //make first plot
    rgraph.plot();
}

You should see some labels now.
The thing is that... well, they are not centered. So we'll just add an onPlaceLabel method to the controller in order to do that, since the onPlaceLabel method is called after labels have been placed.

So the js code should now look like:

function init() {
  //Set node interpolation to linear (can also be 'polar')
  Config.interpolation = "linear";
  //Set distance for concentric circles
  Config.levelDistance = 100;

  var json= //data defined previously

  //Create a new canvas instance.
  var canvas = new Canvas('mycanvas', {
    //Where to inject the canvas. Any div container will do.
    'injectInto':'infovis',
    //width and height for canvas. Default's to 200.
    'width': 900,
    'height':500,
    //Canvas styles
    'styles': {
        'fillStyle': '#ccddee',
        'strokeStyle': '#772277'
    },
    //Add a background canvas for plotting
    //concentric circles.
    'backgroundCanvas': {
        //Add Canvas styles for the bck canvas.
      'styles': {
            'fillStyle': '#444',
            'strokeStyle': '#444'
        },
        //Add the initialization and plotting functions.
        'impl': {
            'init': $empty,
            'plot': function(canvas, ctx) {
                var times = 6, d = Config.levelDistance;
                var pi2 = Math.PI*2;
                for(var i=1; i<=times; i++) {
                    ctx.beginPath();
                    ctx.arc(0, 0, i * d, 0, pi2, true);
                    ctx.stroke();
                    ctx.closePath();
                }
            }
        }
    }
 });

  var rgraph= new RGraph(canvas,  {
    //Add a controller to make the tree move on click.
    onCreateLabel: function(domElement, node) {
      var d = $(domElement);
      d.set('html', node.name).addEvents({
        'click': function() {
          rgraph.onClick(d.id);
        }
      });
    },

  //Take off previous width and height styles and
  //add half of the *actual* label width to the left position
  // That will center your label (do the math man).
    onPlaceLabel: function(domElement, node) {
      domElement.innerHTML = '';
      domElement.innerHTML = node.name;
      var left = parseInt(domElement.style.left);
      domElement.style.width = '';
      domElement.style.height = '';
      var w = domElement.offsetWidth;
      domElement.style.left = (left - w /2) + 'px';
    }

   });

    //load tree from tree data.
    rgraph.loadTreeFromJSON(json);
    //compute positions
    rgraph.compute();
    //make first plot
    rgraph.plot();
}

You should see some centered labels now!

Labels already have the onclick event handler to move the graph. You set that onCreateLabel.

Remember there are lots of other controller methods!

Remember also that you can change the animation time and the frames per second in the animation with Config.animationTime and Config.fps.
Hope it was helpful.

ST quick tutorial

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

Note: I’ll be using Mootools for this tutorial. However, this visualization can be used without the Mootools library. You can find a Mootools build in the extras folder of the library.

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

We are going to work with this tree JSON structure:

var json = {"id":"node02",
 "name":"0.2",
 "data":[
    {"key":"key1",
     "value":2},
    {"key":"key2",
     "value":-86}],
 "children":[
    {"id":"node13",
     "name":"1.3",
     "data":[
        {"key":"key1",
         "value":7},
        {"key":"key2",
         "value":73}],
     "children":[
        {"id":"node24",
         "name":"2.4",
         "data":[
            {"key":"key1",
             "value":2},
            {"key":"key2",
             "value":-49}],
         "children":[
            {"id":"node35",
             "name":"3.5",
             "data":[
                {"key":"key1",
                 "value":8},
                {"key":"key2",
                 "value":-10}],
             "children":[
                {"id":"node46",
                 "name":"4.6",
                 "data":[
                    {"key":"key1",
                     "value":10},
                    {"key":"key2",
                     "value":74}],
                 "children":[]},
                {"id":"node47",
                 "name":"4.7",
                 "data":[
                    {"key":"key1",
                     "value":3},
                    {"key":"key2",
                     "value":-37}],
                 "children":[]}]},
            {"id":"node38",
             "name":"3.8",
             "data":[
                {"key":"key1",
                 "value":8},
                {"key":"key2",
                 "value":88}],
             "children":[
                {"id":"node49",
                 "name":"4.9",
                 "data":[
                    {"key":"key1",
                     "value":2},
                    {"key":"key2",
                     "value":-67}],
                 "children":[]},
                {"id":"node410",
                 "name":"4.10",
                 "data":[
                    {"key":"key1",
                     "value":10},
                    {"key":"key2",
                     "value":38}],
                 "children":[]},
                {"id":"node411",
                 "name":"4.11",
                 "data":[
                    {"key":"key1",
                     "value":5},
                    {"key":"key2",
                     "value":-77}],
                 "children":[]}]}]},
        {"id":"node212",
         "name":"2.12",
         "data":[
            {"key":"key1",
             "value":3},
            {"key":"key2",
             "value":-99}],
         "children":[
            {"id":"node313",
             "name":"3.13",
             "data":[
                {"key":"key1",
                 "value":9},
                {"key":"key2",
                 "value":48}],
             "children":[
                {"id":"node414",
                 "name":"4.14",
                 "data":[
                    {"key":"key1",
                     "value":8},
                    {"key":"key2",
                     "value":-19}],
                 "children":[]},
                {"id":"node415",
                 "name":"4.15",
                 "data":[
                    {"key":"key1",
                     "value":10},
                    {"key":"key2",
                     "value":61}],
                 "children":[]},
                {"id":"node416",
                 "name":"4.16",
                 "data":[
                    {"key":"key1",
                     "value":2},
                    {"key":"key2",
                     "value":83}],
                 "children":[]}]},
            {"id":"node317",
             "name":"3.17",
             "data":[
                {"key":"key1",
                 "value":4},
                {"key":"key2",
                 "value":-18}],
             "children":[
                {"id":"node418",
                 "name":"4.18",
                 "data":[
                    {"key":"key1",
                     "value":9},
                    {"key":"key2",
                     "value":-58}],
                 "children":[]},
                {"id":"node419",
                 "name":"4.19",
                 "data":[
                    {"key":"key1",
                     "value":6},
                    {"key":"key2",
                     "value":-35}],
                 "children":[]},
                {"id":"node420",
                 "name":"4.20",
                 "data":[
                    {"key":"key1",
                     "value":1},
                    {"key":"key2",
                     "value":84}],
                 "children":[]},
                {"id":"node421",
                 "name":"4.21",
                 "data":[
                    {"key":"key1",
                     "value":1},
                    {"key":"key2",
                     "value":19}],
                 "children":[]}]}]},
        {"id":"node222",
         "name":"2.22",
         "data":[
            {"key":"key1",
             "value":7},
            {"key":"key2",
             "value":-3}],
         "children":[
            {"id":"node323",
             "name":"3.23",
             "data":[
                {"key":"key1",
                 "value":9},
                {"key":"key2",
                 "value":-53}],
             "children":[
                {"id":"node424",
                 "name":"4.24",
                 "data":[
                    {"key":"key1",
                     "value":4},
                    {"key":"key2",
                     "value":63}],
                 "children":[]},
                {"id":"node425",
                 "name":"4.25",
                 "data":[
                    {"key":"key1",
                     "value":8},
                    {"key":"key2",
                     "value":38}],
                 "children":[]},
                {"id":"node426",
                 "name":"4.26",
                 "data":[
                    {"key":"key1",
                     "value":5},
                    {"key":"key2",
                     "value":84}],
                 "children":[]}]}]}]},
    {"id":"node127",
     "name":"1.27",
     "data":[
        {"key":"key1",
         "value":4},
        {"key":"key2",
         "value":34}],
     "children":[
        {"id":"node228",
         "name":"2.28",
         "data":[
            {"key":"key1",
             "value":6},
            {"key":"key2",
             "value":-8}],
         "children":[
            {"id":"node329",
             "name":"3.29",
             "data":[
                {"key":"key1",
                 "value":4},
                {"key":"key2",
                 "value":-48}],
             "children":[
                {"id":"node430",
                 "name":"4.30",
                 "data":[
                    {"key":"key1",
                     "value":3},
                    {"key":"key2",
                     "value":-64}],
                 "children":[]},
                {"id":"node431",
                 "name":"4.31",
                 "data":[
                    {"key":"key1",
                     "value":6},
                    {"key":"key2",
                     "value":-79}],
                 "children":[]},
                {"id":"node432",
                 "name":"4.32",
                 "data":[
                    {"key":"key1",
                     "value":2},
                    {"key":"key2",
                     "value":18}],
                 "children":[]}]},
            {"id":"node333",
             "name":"3.33",
             "data":[
                {"key":"key1",
                 "value":1},
                {"key":"key2",
                 "value":96}],
             "children":[
                {"id":"node434",
                 "name":"4.34",
                 "data":[
                    {"key":"key1",
                     "value":4},
                    {"key":"key2",
                     "value":32}],
                 "children":[]},
                {"id":"node435",
                 "name":"4.35",
                 "data":[
                    {"key":"key1",
                     "value":3},
                    {"key":"key2",
                     "value":-52}],
                 "children":[]}]},
            {"id":"node336",
             "name":"3.36",
             "data":[
                {"key":"key1",
                 "value":6},
                {"key":"key2",
                 "value":81}],
             "children":[
                {"id":"node437",
                 "name":"4.37",
                 "data":[
                    {"key":"key1",
                     "value":4},
                    {"key":"key2",
                     "value":-51}],
                 "children":[]},
                {"id":"node438",
                 "name":"4.38",
                 "data":[
                    {"key":"key1",
                     "value":9},
                    {"key":"key2",
                     "value":14}],
                 "children":[]},
                {"id":"node439",
                 "name":"4.39",
                 "data":[
                    {"key":"key1",
                     "value":8},
                    {"key":"key2",
                     "value":18}],
                 "children":[]},
                {"id":"node440",
                 "name":"4.40",
                 "data":[
                    {"key":"key1",
                     "value":7},
                    {"key":"key2",
                     "value":-3}],
                 "children":[]}]},
            {"id":"node341",
             "name":"3.41",
             "data":[
                {"key":"key1",
                 "value":9},
                {"key":"key2",
                 "value":-56}],
             "children":[
                {"id":"node442",
                 "name":"4.42",
                 "data":[
                    {"key":"key1",
                     "value":10},
                    {"key":"key2",
                     "value":56}],
                 "children":[]},
                {"id":"node443",
                 "name":"4.43",
                 "data":[
                    {"key":"key1",
                     "value":6},
                    {"key":"key2",
                     "value":-90}],
                 "children":[]},
                {"id":"node444",
                 "name":"4.44",
                 "data":[
                    {"key":"key1",
                     "value":10},
                    {"key":"key2",
                     "value":-64}],
                 "children":[]},
                {"id":"node445",
                 "name":"4.45",
                 "data":[
                    {"key":"key1",
                     "value":7},
                    {"key":"key2",
                     "value":-82}],
                 "children":[]}]}]},
        {"id":"node246",
         "name":"2.46",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":-16}],
         "children":[
            {"id":"node347",
             "name":"3.47",
             "data":[
                {"key":"key1",
                 "value":8},
                {"key":"key2",
                 "value":-41}],
             "children":[
                {"id":"node448",
                 "name":"4.48",
                 "data":[
                    {"key":"key1",
                     "value":7},
                    {"key":"key2",
                     "value":17}],
                 "children":[]},
                {"id":"node449",
                 "name":"4.49",
                 "data":[
                    {"key":"key1",
                     "value":7},
                    {"key":"key2",
                     "value":24}],
                 "children":[]},
                {"id":"node450",
                 "name":"4.50",
                 "data":[
                    {"key":"key1",
                     "value":6},
                    {"key":"key2",
                     "value":-11}],
                 "children":[]},
                {"id":"node451",
                 "name":"4.51",
                 "data":[
                    {"key":"key1",
                     "value":1},
                    {"key":"key2",
                     "value":-77}],
                 "children":[]}]},
            {"id":"node352",
             "name":"3.52",
             "data":[
                {"key":"key1",
                 "value":8},
                {"key":"key2",
                 "value":20}],
             "children":[
                {"id":"node453",
                 "name":"4.53",
                 "data":[
                    {"key":"key1",
                     "value":5},
                    {"key":"key2",
                     "value":20}],
                 "children":[]},
                {"id":"node454",
                 "name":"4.54",
                 "data":[
                    {"key":"key1",
                     "value":6},
                    {"key":"key2",
                     "value":77}],
                 "children":[]},
                {"id":"node455",
                 "name":"4.55",
                 "data":[
                    {"key":"key1",
                     "value":2},
                    {"key":"key2",
                     "value":52}],
                 "children":[]},
                {"id":"node456",
                 "name":"4.56",
                 "data":[
                    {"key":"key1",
                     "value":3},
                    {"key":"key2",
                     "value":41}],
                 "children":[]}]},
            {"id":"node357",
             "name":"3.57",
             "data":[
                {"key":"key1",
                 "value":2},
                {"key":"key2",
                 "value":-17}],
             "children":[
                {"id":"node458",
                 "name":"4.58",
                 "data":[
                    {"key":"key1",
                     "value":2},
                    {"key":"key2",
                     "value":4}],
                 "children":[]}]},
            {"id":"node359",
             "name":"3.59",
             "data":[
                {"key":"key1",
                 "value":10},
                {"key":"key2",
                 "value":-79}],
             "children":[
                {"id":"node460",
                 "name":"4.60",
                 "data":[
                    {"key":"key1",
                     "value":10},
                    {"key":"key2",
                     "value":-55}],
                 "children":[]},
                {"id":"node461",
                 "name":"4.61",
                 "data":[
                    {"key":"key1",
                     "value":4},
                    {"key":"key2",
                     "value":92}],
                 "children":[]},
                {"id":"node462",
                 "name":"4.62",
                 "data":[
                    {"key":"key1",
                     "value":10},
                    {"key":"key2",
                     "value":-40}],
                 "children":[]},
                {"id":"node463",
                 "name":"4.63",
                 "data":[
                    {"key":"key1",
                     "value":4},
                    {"key":"key2",
                     "value":57}],
                 "children":[]}]}]},
        {"id":"node264",
         "name":"2.64",
         "data":[
            {"key":"key1",
             "value":3},
            {"key":"key2",
             "value":91}],
         "children":[
            {"id":"node365",
             "name":"3.65",
             "data":[
                {"key":"key1",
                 "value":5},
                {"key":"key2",
                 "value":-51}],
             "children":[
                {"id":"node466",
                 "name":"4.66",
                 "data":[
                    {"key":"key1",
                     "value":6},
                    {"key":"key2",
                     "value":50}],
                 "children":[]},
                {"id":"node467",
                 "name":"4.67",
                 "data":[
                    {"key":"key1",
                     "value":2},
                    {"key":"key2",
                     "value":16}],
                 "children":[]}]},
            {"id":"node368",
             "name":"3.68",
             "data":[
                {"key":"key1",
                 "value":9},
                {"key":"key2",
                 "value":50}],
             "children":[
                {"id":"node469",
                 "name":"4.69",
                 "data":[
                    {"key":"key1",
                     "value":10},
                    {"key":"key2",
                     "value":-22}],
                 "children":[]},
                {"id":"node470",
                 "name":"4.70",
                 "data":[
                    {"key":"key1",
                     "value":5},
                    {"key":"key2",
                     "value":-71}],
                 "children":[]}]}]},
        {"id":"node271",
         "name":"2.71",
         "data":[
            {"key":"key1",
             "value":3},
            {"key":"key2",
             "value":-40}],
         "children":[
            {"id":"node372",
             "name":"3.72",
             "data":[
                {"key":"key1",
                 "value":7},
                {"key":"key2",
                 "value":-7}],
             "children":[
                {"id":"node473",
                 "name":"4.73",
                 "data":[
                    {"key":"key1",
                     "value":8},
                    {"key":"key2",
                     "value":-35}],
                 "children":[]},
                {"id":"node474",
                 "name":"4.74",
                 "data":[
                    {"key":"key1",
                     "value":8},
                    {"key":"key2",
                     "value":92}],
                 "children":[]},
                {"id":"node475",
                 "name":"4.75",
                 "data":[
                    {"key":"key1",
                     "value":2},
                    {"key":"key2",
                     "value":64}],
                 "children":[]},
                {"id":"node476",
                 "name":"4.76",
                 "data":[
                    {"key":"key1",
                     "value":7},
                    {"key":"key2",
                     "value":-95}],
                 "children":[]}]},
            {"id":"node377",
             "name":"3.77",
             "data":[
                {"key":"key1",
                 "value":3},
                {"key":"key2",
                 "value":-46}],
             "children":[
                {"id":"node478",
                 "name":"4.78",
                 "data":[
                    {"key":"key1",
                     "value":6},
                    {"key":"key2",
                     "value":56}],
                 "children":[]},
                {"id":"node479",
                 "name":"4.79",
                 "data":[
                    {"key":"key1",
                     "value":2},
                    {"key":"key2",
                     "value":-40}],
                 "children":[]},
                {"id":"node480",
                 "name":"4.80",
                 "data":[
                    {"key":"key1",
                     "value":2},
                    {"key":"key2",
                     "value":-88}],
                 "children":[]}]},
            {"id":"node381",
             "name":"3.81",
             "data":[
                {"key":"key1",
                 "value":6},
                {"key":"key2",
                 "value":-81}],
             "children":[
                {"id":"node482",
                 "name":"4.82",
                 "data":[
                    {"key":"key1",
                     "value":7},
                    {"key":"key2",
                     "value":-14}],
                 "children":[]}]},
            {"id":"node383",
             "name":"3.83",
             "data":[
                {"key":"key1",
                 "value":4},
                {"key":"key2",
                 "value":32}],
             "children":[
                {"id":"node484",
                 "name":"4.84",
                 "data":[
                    {"key":"key1",
                     "value":6},
                    {"key":"key2",
                     "value":36}],
                 "children":[]},
                {"id":"node485",
                 "name":"4.85",
                 "data":[
                    {"key":"key1",
                     "value":9},
                    {"key":"key2",
                     "value":96}],
                 "children":[]},
                {"id":"node486",
                 "name":"4.86",
                 "data":[
                    {"key":"key1",
                     "value":10},
                    {"key":"key2",
                     "value":13}],
                 "children":[]},
                {"id":"node487",
                 "name":"4.87",
                 "data":[
                    {"key":"key1",
                     "value":4},
                    {"key":"key2",
                     "value":96}],
                 "children":[]}]}]}]}]};

Put this HTML in your page:

<html>
	<head>

	<link type="text/css" rel="stylesheet" href="/static/css/example-spacetree.css" />
<!--[if IE]>
<script type="text/javascript" src="/static/js/excanvas.js"></script>
<![endif]-->
	<script type="text/javascript" src="/static/js/mootools-1.2.js" ></script>
	<script type="text/javascript" src="/static/js/spacetree/Spacetree.js" ></script>
	<script type="text/javascript" src="/static/js/example/example-spacetree.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.

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

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

#infovis {
	background-color:#222;
	position:relative;
	width:900px;
	height:500px;
}

a, a:link, a:visited {
	color:#343439;
}

.node {
	background-color:transparent;
	font-weight:bold;
	overflow:hidden;
	text-decoration:none;
	position:absolute;
	text-align:center;
	padding:4px 1px 1px 1px;
}

.node:hover {
	color:#393434;
}

.hidden{
	display:none;
}

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

function init() {
    var json= //data defined previously
      //Create a new canvas instance.
      var canvas = new Canvas('mycanvas', {
         //Where to inject canvas. Any HTML container will do.
         'injectInto':'infovis',
         //Set width and height, default's to 200.
         'width': 900,
         'height': 500,
         //Set a background color in case the browser
         //does not support clearing a specific area.
        'backgroundColor': '#222',
        //Set canvas styles.
        'styles': {
            'fillStyle': '#ccb',
            'strokeStyle': '#ccb'
        }
      });
    //Create a new ST instance
    var st= new ST(canvas);
    //load json data
    st.loadFromJSON(json);
    //compute node positions and layout
    st.compute();
    //optional: make a translation of the tree
    Tree.Geometry.translate(st.tree, new Complex(-200, 0), "startPos");
    //Emulate a click on the root node.
    st.onClick(st.tree.id);
}

You should see a spacetree up and running (don’t worry if you can’t interact with it, we’ll add click event handlers on the labels below).

Some notes:

  • I f you want to know more about the DOM structure created by the Canvas object and about the options for the controller of this class you can see this post and the object reference
  • You can define how many levels to expand by setting Config.levelsToShow. However, if the expanded subtree height is greater than the canvas height, the spacetree might not show all levels. Unfortunately, this doesn’t happen when the width of the subtree expanded is greater than the canvas width (divided by two).

Adding event handlers to the Spacetree

Let’s add an onclick event to the labels for triggering the Spacetree animation.

This is done by implementing an onCreateLabel controller method and passing it to the Spacetree constructor.
We can also configure a different linewith and color for the nodes and edges that belong to the path between the root node and the clicked node.
This is done by implementing the onBeforePlotNode, onAfterPlotNode, onBeforePlotLine and onAfterPlotLine controller methods in order to change the fillStyle and strokeStyle canvas properties. To know more about these canvas properties check this post.

The code would now be:

function init() {
    var json= //data defined previously

    //Containers for fillStyle, strokeStyle and lineWith canvas properties.
    var fStyle, sStyle, lineWidth;
     //Create a new canvas instance.
      var canvas = new Canvas('mycanvas', {
         //Where to inject canvas. Any HTML container will do.
         'injectInto':'infovis',
         //Set width and height, default's to 200.
         'width': 900,
         'height': 500,
         //Set a background color in case the browser
         //does not support clearing a specific area.
        'backgroundColor': '#222',
        //Set canvas styles.
        'styles': {
            'fillStyle': '#ccb',
            'strokeStyle': '#ccb'
        }
      });
    //Create a new ST instance
    var st= new ST(canvas, {
    //Add an event handler to the node when creating it.
        onCreateLabel: function(label, node) {
            var d = $(label);
            label.id = node.id;
            d.setStyle('cursor', 'pointer')
              .set('html', node.name)
                .addEvent('click', function() {
                st.onClick(d.id);
            });
        },
        //Set color as selected if the node is selected.
        onBeforePlotNode: function(node) {
            var ctx = canvas.getCtx();
            fStyle = ctx.fillStyle;
            sStyle = ctx.strokeStyle;
            if(node.selected) {
                ctx.fillStyle = "#ff7";
                ctx.strokeStyle = "#eed";
            }
        },
        //Restore color.
        onAfterPlotNode: function(node) {
            var ctx = canvas.getCtx();
            ctx.fillStyle = fStyle;
            ctx.stroleStyle = sStyle;
        },
        //Set color as selected if the edge belongs to the path.
        onBeforePlotLine: function(adj) {
            var ctx = canvas.getCtx();
            lineWidth = ctx.lineWidth;
            sStyle = ctx.strokeStyle;
            if(adj.nodeFrom.selected && adj.nodeTo.selected) {
                ctx.strokeStyle = "#eed";
                ctx.lineWidth = 3;
            }
        },
        //Restore color and line width
        onAfterPlotLine: function(adj) {
            var ctx = canvas.getCtx();
            ctx.lineWidth = lineWidth;
            ctx.stroleStyle = sStyle;
        }

    });
    //load json data
    st.loadFromJSON(json);
    //compute node positions and layout
    st.compute();
    //optional: make a translation of the tree
    Tree.Geometry.translate(st.tree, new Complex(-200, 0), "startPos");
    //Emulate a click on the root node.
    st.onClick(st.tree.id);
}

Customizing the Spacetree

The default layout for the spacetree is “left”. That means that the root node always lies at the left of the visualization. You can set the tree layout to “top”, “right” and “bottom” though.

For doing this we are going to add a dropdown in the html page:

<select id="switch">
          <option>left</option>
          <option>top</option>
          <option>right</option>
          <option>bottom</option>
        </select>

Now lets add the change event handler at the bottom of the JS file.

//Add input handler to switch spacetree orientation.
  var select = $('switch').addEvent('change', function() {
    var index = select.selectedIndex;
    var or = select.options[index].text;
    select.disabled = true;
    st.switchPosition(or, {
    onComplete: function() {
      select.disabled = false;
    }
    });
  });

Now if you change the value of the dropdown you should be able to switch the Spacetree orientation. Hows that!

Remember that you can also add controlers to the spacetree!. Take a look at the on controllers section and some examples with the hypertree.

Hope it was helpful!

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 or TM.Strip 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 dimensions. 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-1.2.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.2 which comes packaged with the library (in the extras folder). You can also download it 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 rootId property to whatever id you like in the controller object passed to the TM constructor.

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 Color.minValue and Color.maxValue parameters for the treemap controller.
  • You can also choose the color range for your visualization, this is done by setting the Color.minColorValue and Color.maxColorValue parameters. These properties take an array of 3 integers each describing an RGB value.
  • Finally, to enable treemap coloring you must set the property Color.allow to true.

So the init javascript function would now look like:

function init() {
  var json = //..json data
  var tm = new TM.Squarified({
    //main container id.
    rootId: 'infovis',
    //orientation
    orientation: "v",

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

You should see a colored treemap now.

Finally, let’s put nice tooltips! We’ll do this by using the Tip Mootools class.
First, we’ll define an onAfterCompute controller method to query for all nodes that will be displaying information (like .head and .leaf nodes) and assign the information to be displayed. To know more about this please check the docs for the Tips Mootools plug in
I also define some extra methods that convert the dataset to HTML.
I also allow tooltips by setting tips to true.

So the JavaScript file should now look like this:

function init() {
  var json = //...same json data as before...

  var tm = new TM.Squarified({
    //main container id.
    rootId: 'infovis',
    //orientation
    orientation: "v",
    //Allow tips for treemap
     tips: true,

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

    onAfterCompute: function() {
      var that = this, parent;
      $$('#infovis .leaf', '#infovis .head').each(function(elem, i) {
        //get the JSON tree node element having the same id
        //as the dom element queried and makeTip.
        if(p = elem.getParent()) {
          var sTree = TreeUtil.getSubtree(tm.tree, p.id);
          if(sTree) that.makeTip(elem, sTree);
        }
      });
    },
//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.store('tip:title', title).store('tip:text', 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.

Hypertree quick tutorial

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

Note: I’ll be using Mootools for this tutorial. However, this visualization can be used without the Mootools library. You can find a Mootools build in the extras folder of the library.

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

We are going to work with this tree JSON structure:

var json = {"id":"node02",
"name":"0.2",
"data":[
{"key":"key1",
"value":9},
{"key":"key2",
"value":71}],
"children":[
{"id":"node13",
"name":"1.3",
"data":[
{"key":"key1",
"value":6},
{"key":"key2",
"value":-9}],
"children":[
{"id":"node24",
"name":"2.4",
"data":[
{"key":"key1",
"value":3},
{"key":"key2",
"value":-42}],
"children":[]},
{"id":"node25",
"name":"2.5",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":59}],
"children":[]},
{"id":"node26",
"name":"2.6",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":-50}],
"children":[]},
{"id":"node27",
"name":"2.7",
"data":[
{"key":"key1",
"value":3},
{"key":"key2",
"value":-78}],
"children":[]}]},
{"id":"node18",
"name":"1.8",
"data":[
{"key":"key1",
"value":1},
{"key":"key2",
"value":79}],
"children":[
{"id":"node29",
"name":"2.9",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":77}],
"children":[]},
{"id":"node210",
"name":"2.10",
"data":[
{"key":"key1",
"value":6},
{"key":"key2",
"value":30}],
"children":[]},
{"id":"node211",
"name":"2.11",
"data":[
{"key":"key1",
"value":3},
{"key":"key2",
"value":-44}],
"children":[]}]},
{"id":"node112",
"name":"1.12",
"data":[
{"key":"key1",
"value":7},
{"key":"key2",
"value":94}],
"children":[
{"id":"node213",
"name":"2.13",
"data":[
{"key":"key1",
"value":3},
{"key":"key2",
"value":99}],
"children":[]},
{"id":"node214",
"name":"2.14",
"data":[
{"key":"key1",
"value":4},
{"key":"key2",
"value":-72}],
"children":[]},
{"id":"node215",
"name":"2.15",
"data":[
{"key":"key1",
"value":10},
{"key":"key2",
"value":17}],
"children":[]},
{"id":"node216",
"name":"2.16",
"data":[
{"key":"key1",
"value":6},
{"key":"key2",
"value":53}],
"children":[]},
{"id":"node217",
"name":"2.17",
"data":[
{"key":"key1",
"value":4},
{"key":"key2",
"value":-96}],
"children":[]},
{"id":"node218",
"name":"2.18",
"data":[
{"key":"key1",
"value":10},
{"key":"key2",
"value":-84}],
"children":[]},
{"id":"node219",
"name":"2.19",
"data":[
{"key":"key1",
"value":9},
{"key":"key2",
"value":-4}],
"children":[]},
{"id":"node220",
"name":"2.20",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":66}],
"children":[]}]},
{"id":"node121",
"name":"1.21",
"data":[
{"key":"key1",
"value":10},
{"key":"key2",
"value":0}],
"children":[
{"id":"node222",
"name":"2.22",
"data":[
{"key":"key1",
"value":7},
{"key":"key2",
"value":66}],
"children":[]},
{"id":"node223",
"name":"2.23",
"data":[
{"key":"key1",
"value":10},
{"key":"key2",
"value":-78}],
"children":[]},
{"id":"node224",
"name":"2.24",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":-91}],
"children":[]},
{"id":"node225",
"name":"2.25",
"data":[
{"key":"key1",
"value":7},
{"key":"key2",
"value":-51}],
"children":[]},
{"id":"node226",
"name":"2.26",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":25}],
"children":[]},
{"id":"node227",
"name":"2.27",
"data":[
{"key":"key1",
"value":7},
{"key":"key2",
"value":30}],
"children":[]},
{"id":"node228",
"name":"2.28",
"data":[
{"key":"key1",
"value":3},
{"key":"key2",
"value":-43}],
"children":[]}]},
{"id":"node129",
"name":"1.29",
"data":[
{"key":"key1",
"value":3},
{"key":"key2",
"value":-89}],
"children":[
{"id":"node230",
"name":"2.30",
"data":[
{"key":"key1",
"value":6},
{"key":"key2",
"value":96}],
"children":[]},
{"id":"node231",
"name":"2.31",
"data":[
{"key":"key1",
"value":1},
{"key":"key2",
"value":-21}],
"children":[]},
{"id":"node232",
"name":"2.32",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":17}],
"children":[]},
{"id":"node233",
"name":"2.33",
"data":[
{"key":"key1",
"value":6},
{"key":"key2",
"value":42}],
"children":[]}]},
{"id":"node134",
"name":"1.34",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":84}],
"children":[
{"id":"node235",
"name":"2.35",
"data":[
{"key":"key1",
"value":9},
{"key":"key2",
"value":-14}],
"children":[]},
{"id":"node236",
"name":"2.36",
"data":[
{"key":"key1",
"value":7},
{"key":"key2",
"value":60}],
"children":[]},
{"id":"node237",
"name":"2.37",
"data":[
{"key":"key1",
"value":1},
{"key":"key2",
"value":-71}],
"children":[]}]},
{"id":"node138",
"name":"1.38",
"data":[
{"key":"key1",
"value":9},
{"key":"key2",
"value":-70}],
"children":[
{"id":"node239",
"name":"2.39",
"data":[
{"key":"key1",
"value":10},
{"key":"key2",
"value":-69}],
"children":[]},
{"id":"node240",
"name":"2.40",
"data":[
{"key":"key1",
"value":4},
{"key":"key2",
"value":-31}],
"children":[]},
{"id":"node241",
"name":"2.41",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":-5}],
"children":[]},
{"id":"node242",
"name":"2.42",
"data":[
{"key":"key1",
"value":7},
{"key":"key2",
"value":62}],
"children":[]},
{"id":"node243",
"name":"2.43",
"data":[
{"key":"key1",
"value":9},
{"key":"key2",
"value":91}],
"children":[]}]},
{"id":"node144",
"name":"1.44",
"data":[
{"key":"key1",
"value":6},
{"key":"key2",
"value":10}],
"children":[
{"id":"node245",
"name":"2.45",
"data":[
{"key":"key1",
"value":7},
{"key":"key2",
"value":-2}],
"children":[]},
{"id":"node246",
"name":"2.46",
"data":[
{"key":"key1",
"value":1},
{"key":"key2",
"value":93}],
"children":[]},
{"id":"node247",
"name":"2.47",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":70}],
"children":[]},
{"id":"node248",
"name":"2.48",
"data":[
{"key":"key1",
"value":4},
{"key":"key2",
"value":-40}],
"children":[]}]},
{"id":"node149",
"name":"1.49",
"data":[
{"key":"key1",
"value":6},
{"key":"key2",
"value":-58}],
"children":[
{"id":"node250",
"name":"2.50",
"data":[
{"key":"key1",
"value":4},
{"key":"key2",
"value":-41}],
"children":[]},
{"id":"node251",
"name":"2.51",
"data":[
{"key":"key1",
"value":7},
{"key":"key2",
"value":-91}],
"children":[]},
{"id":"node252",
"name":"2.52",
"data":[
{"key":"key1",
"value":5},
{"key":"key2",
"value":-21}],
"children":[]},
{"id":"node253",
"name":"2.53",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":-69}],
"children":[]},
{"id":"node254",
"name":"2.54",
"data":[
{"key":"key1",
"value":10},
{"key":"key2",
"value":5}],
"children":[]},
{"id":"node255",
"name":"2.55",
"data":[
{"key":"key1",
"value":5},
{"key":"key2",
"value":-43}],
"children":[]},
{"id":"node256",
"name":"2.56",
"data":[
{"key":"key1",
"value":6},
{"key":"key2",
"value":64}],
"children":[]},
{"id":"node257",
"name":"2.57",
"data":[
{"key":"key1",
"value":10},
{"key":"key2",
"value":-60}],
"children":[]}]},
{"id":"node158",
"name":"1.58",
"data":[
{"key":"key1",
"value":7},
{"key":"key2",
"value":-63}],
"children":[
{"id":"node259",
"name":"2.59",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":86}],
"children":[]},
{"id":"node260",
"name":"2.60",
"data":[
{"key":"key1",
"value":4},
{"key":"key2",
"value":13}],
"children":[]},
{"id":"node261",
"name":"2.61",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":-70}],
"children":[]},
{"id":"node262",
"name":"2.62",
"data":[
{"key":"key1",
"value":5},
{"key":"key2",
"value":-83}],
"children":[]},
{"id":"node263",
"name":"2.63",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":-98}],
"children":[]},
{"id":"node264",
"name":"2.64",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":-79}],
"children":[]},
{"id":"node265",
"name":"2.65",
"data":[
{"key":"key1",
"value":9},
{"key":"key2",
"value":10}],
"children":[]},
{"id":"node266",
"name":"2.66",
"data":[
{"key":"key1",
"value":6},
{"key":"key2",
"value":17}],
"children":[]},
{"id":"node267",
"name":"2.67",
"data":[
{"key":"key1",
"value":8},
{"key":"key2",
"value":26}],
"children":[]}]}]};

Put this HTML in your page:

<html>
<head>

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

<!--[if IE]>
<script type="text/javascript" src="/static/js/excanvas.js"></script>
<![endif]-->
<script type="text/javascript" src="/static/js/mootools-1.2.js" ></script>
<script type="text/javascript" src="/static/js/hypertree/Hypertree.js" ></script>
<script type="text/javascript" src="/static/js/example/example-hypertree.js" ></script>

</head>
<body onload="init();">
<div id="infovis"></div>

</body>
</html>

Note: You’ll probably have to change the paths to the css and javascript files.

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

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

#infovis {
  background-color:#222;
  width:900px;
  height:500px;
}

.node {
  border: 1px solid #555;
  background-color: #ccc;
  color:#222;
  cursor:pointer;
  padding:2px;
  display:none;
}

.hidden {
  display:none;
}

Note: I like the canvas black, just like my coffee.

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

function init() {

var json = //the json structure mentioned above...
  //Create a new canvas instance.
  var canvas = new Canvas('mycanvas', {
    //Where to inject the canvas. Any HTML container will do.
    'injectInto':'infovis',
    //Width and height of canvas, default's to 200.
    'width': 900,
    'height':500,
    //Canvas styles.
    'styles': {
        'fillStyle': '#ddd',
        'strokeStyle': '#dd00bb'
    }
  });
//create a new hypertree instance.
var ht= new Hypertree(canvas);
//feed the hypertree with a JSON structure.
ht.loadTreeFromJSON(json);
//compute node positions
ht.compute();
//plot the hypertree on canvas
ht.plot();
}

You should see a hypertree up and running (don’t worry if it doesn’t move, we’ll add click events later).

Some notes:

  • For more information about what kind of DOM structure the Canvas object creates and what kind of configuration it takes, please see this post, and the Canvas object reference.
  • If you want to know more about the canvas styles properties you can see this section from the canvas tutorial.
  • The Hypertree animation can be triggered by adding custom events to the node labels or by adding a custom event to the canvas object. This will be discussed below.

Customizing the Hypertree

Let’s add some labels!

First, strip off the display:none; line from the .node class in your CSS file.
It should look like this:

.node {
  border: 1px solid #555;
  background-color: #ccc;
  color:#222;
  cursor:pointer;
  padding:2px;
}

Now we are going to add a javascript controller in order to put the name of the nodes into the labels. Since we only need to do this once, we’ll use the onCreateLabel method. If you don’t know what I’m talking about you should probably read the on controllers post first.

So the JavaScript file should look like this now:

function init() {
  var json = //json data mentioned above...
  //Create a new canvas instance.
  var canvas = new Canvas('mycanvas', {
    //Where to inject the canvas. Any HTML container will do.
    'injectInto':'infovis',
    //Width and height of canvas, default's to 200.
    'width': 900,
    'height':500,
    //Canvas styles.
    'styles': {
        'fillStyle': '#ddd',
        'strokeStyle': '#dd00bb'
    }
  });
  var ht= new Hypertree(canvas, {

    onCreateLabel: function(domElement, node) {
      $(domElement).set('html', node.name + " and text");
    }

  });

  ht.loadTreeFromJSON(json);
  ht.compute();
  ht.plot();
}

You should see some labels now.
The thing is that… well, they are not centered. So we’ll just add an onPlaceLabel method to the controller in order to do that, since the onPlaceLabel method is called after labels have been placed.

So the js code should now look like:

function init() {
  var json = //json data...
  //Create a new canvas instance.
  var canvas = new Canvas('mycanvas', {
    //Where to inject the canvas. Any HTML container will do.
    'injectInto':'infovis',
    //Width and height of canvas, default's to 200.
    'width': 900,
    'height':500,
    //Canvas styles.
    'styles': {
        'fillStyle': '#ddd',
        'strokeStyle': '#dd00bb'
    }
  });
  var ht= new Hypertree(canvas, {
    onCreateLabel: function(domElement, node) {
      $(domElement).set('html', node.name + " and text");
    },

    //Take the left style property and
    // substract half of the label actual width.
    onPlaceLabel: function(tag, node) {
      var width = tag.offsetWidth;
      var intX = tag.style.left.toInt();
      intX -= width/2;
      tag.style.left = intX + 'px';
    }

  });

  ht.loadTreeFromJSON(json);
  ht.compute();
  ht.plot();
}

You should see some centered labels now!

Finally, we’ll add an onclick event handler in order to move the tree when clicking on a label, hows that!

We’ll add this method on the onCreateLabel method, just because we only want to add label event handlers once.
So the code should look like:

function init() {
  var json = //some json data
  //Create a new canvas instance.
  var canvas = new Canvas('mycanvas', {
    //Where to inject the canvas. Any HTML container will do.
    'injectInto':'infovis',
    //Width and height of canvas, default's to 200.
    'width': 900,
    'height':500,
    //Canvas styles.
    'styles': {
        'fillStyle': '#ddd',
        'strokeStyle': '#dd00bb'
    }
  });
  var ht= new Hypertree(canvas, {
    onCreateLabel: function(domElement, node) {
      $(domElement).set('html', node.name + " and text").addEvents({
          //Call the "onclick" method from
          //the hypertree to move the hypertree
          //correspondingly.
          //This method takes the clicked node's id.
          'click': function(e) {
          ht.onClick(node.id);
          }
        });

    },

    //Take the left style property and
    //substract half of the label actual width.
    onPlaceLabel: function(tag, node) {
      var width = tag.offsetWidth;
      var intX = tag.style.left.toInt();
      intX -= width/2;
      tag.style.left = intX + 'px';
    }

  });

  ht.loadTreeFromJSON(json);
  ht.compute();
  ht.plot();
}

If you want to see more advanced examples please check the “examples” folder in the library.

Remember that you have more controller methods!

Remember also that you can change the animation time and the frames per second in the animation with Config.animationTime and Config.fps.
Hope it was helpful.