Feeding JSON graph structures to the JIT
0 Comments Published by admin July 2nd, 2008 in JavaScript information visualization toolkit (JIT)Version 1.0.3a of the JIT allows you to load graph structures to the RGraph and Hypertree objects. I chose a different JSON structure for graphs, since JSON tree structures don’t seem conceptually suitable for this task.
Hypertree and RGraph objects have a new method called loadGraphFromJSON(json [,i]) that takes a graph structure (described below) and optionally an index to set a particular node as root for the visualization. Please refer to the documentation for more information.
The graph structure
The JSON graph structure is an array of nodes, each having as properties:
- id a unique identifier for the node.
- name a node’s name.
- data The data property contains a dataset. That is, an array of key-value objects defined by the user. Roughly speaking, this is where you can put some extra information about your node. You’ll be able to access this information at different stages of the computation of the JIT visualizations by using a controller.
- adjacencies An array of strings each representing a nodes id.
For example,
var json = [
{
"id": "aUniqueIdentifier",
"name": "usually a nodes name",
"data": [
{key:"some key", value: "some value"},
{key:"some other key", value: "some other value"}
],
"adjacencies": ["anotherUniqueIdentifier", "yetAnotherUniqueIdentifier" /* ... */]
} /* ... more nodes here ... */ ];
I did a small example of a K6 rendered with a RGraph. The JSON graph structure used for this example is:
var json= [
{"id":"node0",
"name":"node0 name",
"data":[
{"key":"some key",
"value":"some value"},
{"key":"some other key",
"value":"some other value"}],
"adjacencies":["node1","node2","node3","node4","node5"]},
{"id":"node1",
"name":"node1 name",
"data":[
{"key":"some key",
"value":"some value"},
{"key":"some other key",
"value":"some other value"}],
"adjacencies":["node0","node2","node3","node4","node5"]},
{"id":"node2",
"name":"node2 name",
"data":[
{"key":"some key",
"value":"some value"},
{"key":"some other key",
"value":"some other value"}],
"adjacencies":["node0","node1","node3","node4","node5"]},
{"id":"node3",
"name":"node3 name",
"data":[
{"key":"some key",
"value":"some value"},
{"key":"some other key",
"value":"some other value"}],
"adjacencies":["node0","node1","node2","node4","node5"]},
{"id":"node4",
"name":"node4 name",
"data":[
{"key":"some key",
"value":"some value"},
{"key":"some other key",
"value":"some other value"}],
"adjacencies":["node0","node1","node2","node3","node5"]},
{"id":"node5",
"name":"node5 name",
"data":[
{"key":"some key",
"value":"some value"},
{"key":"some other key",
"value":"some other value"}],
"adjacencies":["node0","node1","node2","node3","node4"]}];
You can post any question at the google group for this project.
Enjoy!
JIT version 1.0.2a
1 Comment Published by admin June 8th, 2008 in JavaScript information visualization toolkit (JIT)Just dropping by to say I just released version 1.0.2a of the javascript infovis toolkit. You can also download it from the main page.
It fixes some known bugs on the Spacetree and Hyperbolic Tree visualizations.
I’d like to thank OpenCRX and Charles D. Aylward for pointing those errors out.
I also used version 1.4 of Natural Docs to make the docs.
Please let me know if you find more errors.
Bye!
Animated exploration of Graphs with radial layout video
Closed Published by admin June 2nd, 2008 in JavaScript information visualization toolkit (JIT), UncategorizedI ran into this youtube video that presents all the features to be included in the RGraph visualization. Some of them were mentioned in the previous post (polar interpolation, child ordering), other are already included with the library (the first animation constraint mentioned in the video, ease-in and ease-out transitions, etc). Anyway, I thought this could be interesting.
If you can’t see the embedded video, please access the video by clicking here.
You can also see the “original” paper here.
Further work on JIT
8 Comments Published by admin May 20th, 2008 in JavaScript information visualization toolkit (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
2 Comments Published by admin May 7th, 2008 in JavaScript information visualization toolkit (JIT)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 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/rgraph/RGraph.js" ></script>
<script type="text/javascript" src="/static/js/example/example-rgraph.js" ></script>
</head>
<body onload="init();">
<canvas id="infovis" width="900" height="500"></canvas>
<div id="label_container"></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() {
var json= //data defined previously...
//Create canvas instance with canvas id, fill and stroke colors.
var canvas= new Canvas('infovis', '#ccddee', '#772277');
var rgraph= new RGraph(canvas);
//load graph 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:
- It’s mandatory to put the width and height properties on the canvas html tag.
You could set those properties dynamically, of course, but what I mean is that setting only width and height style properties (as with CSS) isn’t enough. - You could change the label container id by setting the Config.labelContainer property to whatever id you like. Be sure to set that property before making a Canvas instance.
- The Canvas constructor takes 3 parameters: the canvas id, the fillStyle property and the strokeStyle property. If you don’t know what those properties are, take a look at this section from the canvas tutorial.
- You can take off the concentric circles by setting Config.drawConcentricCircles to false. Just be sure you do that before making a canvas or RGraph instance.
Customizing the Graph
Let’s add some labels!
Note: I’ll be using the Mootools library to do this, just because I don’t want to spend time writing low level code that would make the code uglier. You can use any library you want (or none at all) though.
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() {
var json= //data defined previously...
//Create canvas instance with canvas id, fill and stroke colors.
var canvas= new Canvas('infovis', '#ccddee', '#772277');
var rgraph= new RGraph(canvas);
//Add a controller to assign the node's name to the created label.
rgraph.controller = {
onCreateLabel: function(domElement, node) {
domElement.innerHTML = node.name;
}
};
//load graph 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() {
var json= //json data...
//Create canvas instance with canvas id, fill and stroke colors.
var canvas= new Canvas('infovis', '#ccddee', '#772277');
var rgraph= new RGraph(canvas);
//Add a controller to assign the node's name to the created label.
rgraph.controller = {
onCreateLabel: function(domElement, node) {
domElement.innerHTML = node.name;
},
//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) {
var left = parseInt(domElement.style.left);
domElement.style.width = '';
domElement.style.height = '';
var w = domElement.offsetWidth;
domElement.style.left = (left - w /2) + 'px';
}
};
//load graph 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.
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
Closed Published by admin May 7th, 2008 in JavaScript information visualization toolkit (JIT)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 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" /> <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();"> <canvas id="infovis" width="900" height="500"></canvas> <div id="label_container" /> </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;
}
Note: the margin:0;padding:0; on html,body is pretty important to place well the ST labels.
Finally, create an example-spacetree.js file and put this code in it:
function init() {
var json= //json data specified before...
//Create a new canvas instance.
var canvas= new Canvas('infovis');
//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
st.translate(st.tree, new Complex(200, 0), "pos");
//Emulate a click on the root node.
st.onClick(st.tree.id);
}
You should see a spacetree up and running (it may take a few seconds to load).
Some notes:
- It’s mandatory to put the width and height properties on the canvas html tag.
You could set those properties dynamically, of course, but what I mean is that setting only width and height style properties (as with CSS) isn’t enough. - You could change the label container id by setting the Config.labelContainer property to whatever id you like. Be sure to set that property before making a Canvas instance.
- The Canvas constructor takes 1 parameter: the canvas id. To set the fillStyle and strokeStyle properties for nodes which are in path to root or nodes which aren’t you should refer to Config.Node.(strokeStyle|fillStyle|strokeStyleInPath|fillStyleInPath).
- 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).
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” though.
So, put a checkbox in your HTML. Your HTML should look like this:
<html> <head> <link type="text/css" rel="stylesheet" href="/static/css/example-spacetree.css" /> <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();"> <input type="checkbox" id="switch"/> <canvas id="infovis" width="900" height="500"></canvas> <div id="label_container" /> </body> </html>
Note: You can add some style to the checkbox to put it somewhere else.
Now change the JS file to put a handler on the onchange event. It should look like this:
function init() {
var json= //json data specified before...
//Create a new canvas instance.
var canvas= new Canvas('infovis');
//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
st.translate(st.tree, new Complex(200, 0), "pos");
//Emulate a click on the root node.
st.onClick(st.tree.id);
//Add input handler to switch spacetree orientation.
var checkbox = document.getElementById('switch');
checkbox.onchange = function () {
checkbox.disabled = true;
st.switchPosition({onComplete: function() {
checkbox.disabled = false;
}});
};
}
Now if you click on the checkbox 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
4 Comments Published by admin May 7th, 2008 in JavaScript information visualization toolkit (JIT)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;
}
.tool-title {
font-weight: bold;
font-size: 11px;
margin: 0;
color: #9FD4FF;
padding: 8px 8px 4px;
background-color: black;
}
.tool-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();
//We define a controller to the treemap instance.
tm.controller = {
//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.
Hypertree quick tutorial
Closed Published by admin May 7th, 2008 in JavaScript information visualization toolkit (JIT)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 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/hypertree/Hypertree.js" ></script> <script type="text/javascript" src="/static/js/example/example-hypertree.js" ></script> </head> <body onload="init();"> <canvas id="infovis" width="900" height="500"></canvas> <div id="label_container"></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('infovis', '#fff', '#fff');
//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();
//add event handlers to the canvas in order to move the hypertree when I click con the canvas -optional-
ht.prepareCanvasEvents();
}
You should see a hypertree up and running (it may take a few seconds to load).
Some notes:
- It’s mandatory to put the width and height properties on the canvas html tag.
You could set those properties dynamically, of course, but what I mean is that setting only width and height style properties (as with CSS) isn’t enough. - You could change the label container id by setting the Config.labelContainer property to whatever id you like. Be sure to set that property before making a Canvas instance.
- The Canvas constructor takes 3 parameters: the canvas id, the fillStyle property and the strokeStyle property. If you don’t know what those properties are, take a look at this section from the canvas tutorial.
- It’s not mandatory to add the ht.prepareCanvasEvents(); method. This method just adds some event handlers to the canvas tag in order to move the tree when you click on the canvas.
- You can take off the main circle by setting Config.drawMainCircle to false. Just be sure you do that before making a canvas or Hypertree instance.
Customizing the Hypertree
Let’s add some labels!
Note: I’ll be using the Mootools library to do this, just because I don’t want to spend time writing low level code that would make the code uglier. You can use any library you want (or none at all) though.
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...
var canvas= new Canvas('infovis', '#fff', '#fff');
var ht= new Hypertree(canvas);
//Add a controller to assign the node's name to the created label.
ht.controller = {
onCreateLabel: function(domElement, node) {
$(domElement).setHTML(node.name + " and text");
}
};
ht.loadTreeFromJSON(json);
ht.compute();
ht.plot();
ht.prepareCanvasEvents();
}
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...
var canvas= new Canvas('infovis', '#fff', '#fff');
var ht= new Hypertree(canvas);
//Add a controller to assign the node's name to the created label.
ht.controller = {
onCreateLabel: function(domElement, node) {
$(domElement).setHTML(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();
ht.prepareCanvasEvents();
}
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
var canvas= new Canvas('infovis', '#fff', '#fff');
var ht= new Hypertree(canvas);
//Add a controller to assign the node's name to the created label.
ht.controller = {
onCreateLabel: function(domElement, node) {
$(domElement).setHTML(node.name + " and text").addEvents({
//Call the "onclick" method from the hypertree to move the hypertree correspondingly.
//This method takes the native event object. Since Mootools uses a wrapper for this
//event, I have to put e.event to get the native event object.
'click': function(e) {
ht.onClick(e.event);
}
});
},
//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();
ht.prepareCanvasEvents();
}
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.
On controllers
Closed Published by admin April 27th, 2008 in JavaScript information visualization toolkit (JIT)Controllers are a straightforward way to customize the JavaScript infovis toolkit (JIT) visualizations.
A controller is a JavaScript object that “implements” an interface. The interface methods will then be called at different stages of the visualization, allowing you to, for example, place labels and add event handlers to them, performing actions before and after the animation, making ajax - calls to load data dynamically to the tree, etc.
The controller interface is defined as:
var ControllerInterface = {
onCreateLabel: function (domElement, node) {},
onPlaceLabel: function (domElement, node) {},
onCreateElement: function(domElement, node) {},
onBeforeCompute: function (node) {},
onAfterCompute: function () {}
request: function(nodeId, level, onComplete) {},
};
where:
- onCreateLabel(domElement, node) is a method that receives the label dom element as first parameter, and the homologue JSON tree node as second parameter. This method will only be called on label creation. Note that a JSON tree node is a node from the input tree you provided to the visualization. If you don’t know what kind of JSON tree format is used to feed the visualizations, you should take a look at my other post first, feeding JSON tree structures to the JIT.
This method proves useful when adding events to the labels used by the JIT. You should be carefull when adding events though, because some visualizations use the onclick event to add actions. For example, the Spacetree, RGraph and Hypertree visualizations add animation handlers on the onclick event for the labels. - onPlaceLabel(domElement, node) is a method that receives the label dom element as first parameter and the homologue JSON tree node as second parameter. This method is called each time a label has been placed on the visualization, and thus it allows you to update the labels properties, such as size or position. Note that onPlaceLabel will be triggered after updating positions to the labels. That means that, for example, the left and top css properties are allready updated to match the nodes positions.
- onCreateElement(domElement, node) is a method only used by the Treemap visualization. This method is called after a div container for a treemap node has been created. The domElement parameter is the actual div dom element being laid out. So, if you just wanted to add node names to each node div representation, you could just write
onCreateElement: function(domElement, node) { domElement.innerHTML = node.name; } - onBeforeCompute(node) is a method called right before performing all computation and animations to the JIT visualization. In the case of treemaps this method will be called after entering or exiting a tree level. In the case of Hyperbolic trees, RGraphs and Spacetrees, this method will be triggered right before perfoming an animation.
For Treemap visualizations, the node parameter corresponds to the root node of the subtree which will be laid out.
For the Spacetree, Hypertree and RGraph visualizations, the node parameter corresponds to the actual node being clicked or centered on the canvas. - onAfterCompute() is a method triggered right after all animations or computations for the JIT visualizations ended.
- request(nodeId, level, onComplete) is a method only used by the Treemap and Spacetree visualizations. You can use this method to “bufferize” information, so that not all the JSON tree structure is loaded at once. The nodeId parameter is the node actually being requested, the level parameter is the level of the subtree being requested, and the onComplete handler is a function you must call after performing your request. A common structure for the request method could be
request: function(nodeId, level, onComplete) { var data; //make a request call to fill the data object and on complete do: onComplete(nodeId, data); },
Note that you should not declare any of these methods on your controller object if you are not going to use them.
Note also that is not mandatory to provide a controller object to the main classes.
You can find some example uses for the controller object at the spacetree, hypertree, treemap and rgraph tutorials.
Be sure to know what JSON structure feeds the JIT visualizations before you read the tutorials.
Hope it was helpful.
Feeding JSON tree structures to the JIT
Closed Published by admin April 27th, 2008 in JavaScript information visualization toolkit (JIT)The tree structure that feeds the spacetree, hypertree, treemap and rgraph visualizations is always the same.
Roughly speaking, the JSON tree structure consists of tree nodes, each having as properties:
- id a unique identifier for the node.
- name a node’s name.
- data The data property contains a dataset. That is, an array of key-value objects defined by the user. Roughly speaking, this is where you can put some extra information about your node. You’ll be able to access this information at different stages of the computation of the JIT visualizations by using a controller.
- children An array of children nodes, or an empty array if the node is a leaf node.
For example,
var json = {
"id": "aUniqueIdentifier",
"name": "usually a nodes name",
"data": [
{key:"some key", value: "some value"},
{key:"some other key", value: "some other value"}
],
children: [/* other nodes or empty */]
};
About datasets:
Sometimes some dataset objects are read by the JIT classes to perform proper layouts.
For example, the treemap class reads the first object’s value for each node’s dataset to perform calculations about the dimensions of the rectangles laid.
Also, if you enable the Config.Color.allow property, the treemap will add colors on the layout, and these colors will be based on your second dataset object value.
Although it’s not implemented yet, RGraphs will also read the first dataset object value in order to compute node diameters and angular widths.
That’s all for now. I recommend you to read the On controllers section and then some spacetree, hypertree, treemap or RGraph tutorials.
Search
About

I'm Nicolas Garcia Belmonte and I'm a Computer Science engineer from the Buenos Aires Institute of Technology (ITBA) in Argentina. I live in France now.
