Quick Tutorial - HyperTree
This tutorial covers the basics about creating a HyperTree visualization. If you want to know more about this visualization I’d recommend you to visit the documentation for the input JSON data, the Canvas Widget, and the HyperTree layout, where you can find detailed information about its configuration options and controller methods.
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": {},
"children": [{
"id": "node13",
"name": "1.3",
"data": {},
"children": [{
"id": "node24",
"name": "2.4",
"data": {},
"children": []
}, {
"id": "node25",
"name": "2.5",
"data": {},
"children": []
}, {
"id": "node26",
"name": "2.6",
"data": {},
"children": []
}, {
"id": "node27",
"name": "2.7",
"data": {},
"children": []
}]
}, {
"id": "node18",
"name": "1.8",
"data": {},
"children": [{
"id": "node29",
"name": "2.9",
"data": {},
"children": []
}, {
"id": "node210",
"name": "2.10",
"data": {},
"children": []
}, {
"id": "node211",
"name": "2.11",
"data": {},
"children": []
}]
}, {
"id": "node112",
"name": "1.12",
"data": {},
"children": [{
"id": "node213",
"name": "2.13",
"data": {},
"children": []
}, {
"id": "node214",
"name": "2.14",
"data": {},
"children": []
}, {
"id": "node215",
"name": "2.15",
"data": {},
"children": []
}, {
"id": "node216",
"name": "2.16",
"data": {},
"children": []
}, {
"id": "node217",
"name": "2.17",
"data": {},
"children": []
}, {
"id": "node218",
"name": "2.18",
"data": {},
"children": []
}, {
"id": "node219",
"name": "2.19",
"data": {},
"children": []
}, {
"id": "node220",
"name": "2.20",
"data": {},
"children": []
}]
}, {
"id": "node121",
"name": "1.21",
"data": {},
"children": [{
"id": "node222",
"name": "2.22",
"data": {},
"children": []
}, {
"id": "node223",
"name": "2.23",
"data": {},
"children": []
}, {
"id": "node224",
"name": "2.24",
"data": {},
"children": []
}, {
"id": "node225",
"name": "2.25",
"data": {},
"children": []
}, {
"id": "node226",
"name": "2.26",
"data": {},
"children": []
}, {
"id": "node227",
"name": "2.27",
"data": {},
"children": []
}, {
"id": "node228",
"name": "2.28",
"data": {},
"children": []
}]
}, {
"id": "node129",
"name": "1.29",
"data": {},
"children": [{
"id": "node230",
"name": "2.30",
"data": {},
"children": []
}, {
"id": "node231",
"name": "2.31",
"data": {},
"children": []
}, {
"id": "node232",
"name": "2.32",
"data": {},
"children": []
}, {
"id": "node233",
"name": "2.33",
"data": {},
"children": []
}]
}, {
"id": "node134",
"name": "1.34",
"data": {},
"children": [{
"id": "node235",
"name": "2.35",
"data": {},
"children": []
}, {
"id": "node236",
"name": "2.36",
"data": {},
"children": []
}, {
"id": "node237",
"name": "2.37",
"data": {},
"children": []
}]
}, {
"id": "node138",
"name": "1.38",
"data": {},
"children": [{
"id": "node239",
"name": "2.39",
"data": {},
"children": []
}, {
"id": "node240",
"name": "2.40",
"data": {},
"children": []
}, {
"id": "node241",
"name": "2.41",
"data": {},
"children": []
}, {
"id": "node242",
"name": "2.42",
"data": {},
"children": []
}, {
"id": "node243",
"name": "2.43",
"data": {},
"children": []
}]
}, {
"id": "node144",
"name": "1.44",
"data": {},
"children": [{
"id": "node245",
"name": "2.45",
"data": {},
"children": []
}, {
"id": "node246",
"name": "2.46",
"data": {},
"children": []
}, {
"id": "node247",
"name": "2.47",
"data": {},
"children": []
}, {
"id": "node248",
"name": "2.48",
"data": {},
"children": []
}]
}, {
"id": "node149",
"name": "1.49",
"data": {},
"children": [{
"id": "node250",
"name": "2.50",
"data": {},
"children": []
}, {
"id": "node251",
"name": "2.51",
"data": {},
"children": []
}, {
"id": "node252",
"name": "2.52",
"data": {},
"children": []
}, {
"id": "node253",
"name": "2.53",
"data": {},
"children": []
}, {
"id": "node254",
"name": "2.54",
"data": {},
"children": []
}, {
"id": "node255",
"name": "2.55",
"data": {},
"children": []
}, {
"id": "node256",
"name": "2.56",
"data": {},
"children": []
}, {
"id": "node257",
"name": "2.57",
"data": {},
"children": []
}]
}, {
"id": "node158",
"name": "1.58",
"data": {},
"children": [{
"id": "node259",
"name": "2.59",
"data": {},
"children": []
}, {
"id": "node260",
"name": "2.60",
"data": {},
"children": []
}, {
"id": "node261",
"name": "2.61",
"data": {},
"children": []
}, {
"id": "node262",
"name": "2.62",
"data": {},
"children": []
}, {
"id": "node263",
"name": "2.63",
"data": {},
"children": []
}, {
"id": "node264",
"name": "2.64",
"data": {},
"children": []
}, {
"id": "node265",
"name": "2.65",
"data": {},
"children": []
}, {
"id": "node266",
"name": "2.66",
"data": {},
"children": []
}, {
"id": "node267",
"name": "2.67",
"data": {},
"children": []
}]
}]
};
We’ll create three files: an example.html file, an example.css file and an example.js file.
I’ll put these files in the root library folder (i.e “Jit”), so I can access all libraries.
Put this HTML in your example.html page:
<html>
<head>
<link type="text/css" rel="stylesheet" href="example.css" />
<!--[if IE]>
<script type="text/javascript" src="Extras/excanvas.js"></script>
<![endif]-->
<script type="text/javascript" src="jit.js" ></script>
<script type="text/javascript" src="example.js" ></script>
</head>
<body onload="init();">
<div id="infovis"></div>
</body>
</html>
Now, put this code in your example.css file:
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;
}
/* style for the visualization container */
#infovis {
background-color:#222;
width:900px;
height:500px;
}
/* style for the visualization's labels */
.node {
border: 1px solid #555;
background-color: #ccc;
color:#222;
cursor:pointer;
padding:2px;
display:none;
}
.hidden {
display:none;
}
Finally, put this code in your example.js file:
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
});
//create a new hypertree instance.
var ht= new Hypertree(canvas, {
//Add colors for nodes and edges
Node: {
color: '#ddd'
},
Edge: {
color: '#dd00bb'
}
});
//feed the hypertree with the JSON structure.
ht.loadJSON(json);
//compute node positions and plot
ht.refresh();
}
You should see a Hyperbolic Tree up and running (don’t worry if it doesn’t move, we’ll add click events later).
Some notes:
- The JSON structure that feeds the HyperTree is a JSON tree structure. If you want to know more about JSON tree structures or about what other JSON structures can feed the Hypertree (graph structures for example) see the JSON input data entry at the documentation.
- For more information about what kind of DOM structure the Canvas object creates and what kind of configuration it takes, please see the Canvas Widget documentation.
- For more information about the Canvas object in general and what styles can be applied to it I’d recommend you to read this section from the Mozilla Canvas Tutorial.
- The Hyperbolic Tree animation can be triggered by adding custom events to node labels. 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. There are many other controller methods triggered at different stages of the HyperTree that you can find very useful. For more information about this please read the HyperTree documentation.
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
});
var ht= new Hypertree(canvas, {
//Add colors for nodes and edges
Node: {
color: '#ddd'
},
Edge: {
color: '#dd00bb'
},
//Add node names to node labels
onCreateLabel: function(domElement, node) {
domElement.innerHTML = node.name;
}
});
ht.loadJSON(json);
ht.refresh();
}
You should see some labels now.
The thing is that… well, they’re 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 this:
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
});
var ht= new Hypertree(canvas, {
//Add colors for nodes and edges
Node: {
color: '#ddd'
},
Edge: {
color: '#dd00bb'
},
//Add node names to node labels
onCreateLabel: function(domElement, node) {
domElement.innerHTML = node.name;
},
//Take the left style property and
//substract half of the label actual width to
//center the label.
onPlaceLabel: function(tag, node) {
var width = tag.offsetWidth;
var intX = parseInt(tag.style.left);
intX -= width / 2;
tag.style.left = intX + 'px';
}
});
ht.loadJSON(json);
ht.refresh();
}
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 in the onCreateLabel method, just because we only want to add label event handlers once.
So the code should look like this now:
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
});
var ht= new Hypertree(canvas, {
//Add colors for nodes and edges
Node: {
color: '#ddd'
},
Edge: {
color: '#dd00bb'
},
//Add node names to node labels
onCreateLabel: function(domElement, node) {
domElement.innerHTML = node.name;
//Call the "onclick" method from
//the hypertree to move the hypertree
//correspondingly.
//This method takes the clicked node's id.
domElement.onclick = function() {
ht.onClick(node.id);
};
},
//Take the left style property and
//substract half of the label actual width to
//center the label.
onPlaceLabel: function(tag, node) {
var width = tag.offsetWidth;
var intX = parseInt(tag.style.left);
intX -= width / 2;
tag.style.left = intX + 'px';
}
});
ht.loadJSON(json);
ht.refresh();
}
Now click on a label: the hypertree should move!
If you want to see more advanced examples please take a look at the Examples section. Those examples are also packaged with the library (inside the Examples folder).
Hope it was helpful.