A treemap is a type of data diagram which shows a (hierarchical) list of values as nested rectangles. The original version of this class is also part of the Generative Design Library. For this standalone version I added some functionality and renamed/restructured things.
This is work in process!
I decided to publish it here as a seperate library to have it as a pure, independent, tiny and single-purpose class. It might be the right thing for you, if you want to generate and draw a treemap without having all the great but distractive stuff in big libraries like D3.js.
A treemap is one good way of visualizing the sizes of a list of values. It works on plain lists, just like a bar chart does. But the real strength of a treemap is to show relative sizes in hierarchical data. This library helps with parsing or building this hierarchical data and calculating the rectangles. There is no graphics engine attached. But this way you can easiliy use it with every drawing method (plain html, p5.js, snap.svg, paper.js, ...). Have a look at the examples, there I try to show every implemented feature. For the full reference just scroll down to the reference section.
let treemap = new Treemap(20, 20, 400, 300, {
order: 'sort',
direction: 'both',
padding: 4,
});
This will create a treemap at position (x = 20, y = 20) as the upper left corner, with a width of 400 and a height of 300. You can give some options, how to calculate the rectangles. order
could be set to sort
or shuffle
. Default is sort
, which will sort all the items from largest to smallest. From a data visualization point of view that's the best. direction
might be both
, horizontal
or vertical
. A value bigger than 0 for padding
makes every nested item smaller than the containing one. You have to be aware that in fact this produces a "wrong" visualization, because the sizes of the rectangles are not proportional to the values in the data any more. Still, this might be insignificant, if you do not have many values in your data and padding is small compared to the size of the whole treemap.
You can provide data in several ways. If you already have hierarchical data as a (nested) array of values, just do it like this:
let data = [1, 2, 3, 4, [2, 3, 4, 1, 1], 6, [4, 1, 1], [2, 3, 4, [1, 1, 2, 2]], 9, 10, 7, 12];
treemap.addData(data);
The values of a (nested) array might also be objects. In this case you need to specify which value to use for sizing the rectangles.
let data = [
{name:'John', weight:'80'},
{name:'Mary', weight:'65'},
{name:'Carl', weight:'75'},
...
];
treemap.addData(data, {value: 'weight'});
If you have a JSON-like structure like the following it works almost the same. You just have to specify, where to find the children.
let data = {
"name": "02_M",
"files": [{
"name": "M_2_2_01",
"files": [{
"name": "index.html",
"size": 1070
}, {
"name": "M_2_2_01.png",
"size": 7390
}, {
"name": "sketch.js",
"size": 4126
}
]
}, ... ]
}
treemap.addData(data, {children: 'files', value: 'size'});
If you do not already have your data in the needed form you can use the function addItem()
to help you with that. See examples 2_count-up.html
or 4_json-table.html
for how this is done.
In most cases it will look like this:
treemap.calculate();
This produces x and y positions, width and height for all the rectangles in the treemap.
Drawing is always done with a customized drawing function to keep this library independ of any library that helps with drawing stuff. In the following sample, the elements are drawn to the document as divs.
treemap.draw(function(item) {
let div = document.createElement('div');
div.style.left = item.x;
div.style.top = item.y;
div.style.width = item.w;
div.style.height = item.h;
document.body.appendChild(div);
});
The draw()
function parses through all the items of the treemap. You could use a lot of information stored or calculated for that item:
item.x
,item.y
,item.w
,item.h
– Dimensions of the rectitem.minValue
,item.maxValue
- Smallest and largest item inside this itemitem.level
,item.depth
- How deep is this item nested in the tree? The root node has level 0, an end node has depth 0item.itemCount
- Number of items inside this item, counted recursivelyitem.index
- Index of this item inside the parents sorted items array
Creates a new empty Treemap with position (x, y), width and height.
To specify drawing a bit more, you can give drawing options. See method setOptions()
for more information.
Content may be added using addData()
or addItem()
.
Parameters
x
Number – X positiony
Number – Y positionw
Number – Widthh
Number – Heightoptions
Object? – Drawing options
Returns Treemap – The new empty Treemap
X position of the rectangle.
Y position of the rectangle.
Width of the rectangle.
Height of the rectangle.
The minimum value of the items in the items array
The maximum value of the items in the items array
Level of the item; the root node has level 0
The depth of the branch; end nodes have depth 0
The number of items in the complete branch
Index of the item in the sorted items array.
Adds a data structure to the Treemap.
You can provide an object or array of nested subitems. The optional second parameter defines what keys should be used to build the Treemap. This second parameter is in the form
{children:"items", value:"size", data:"name"}
.
The key children
defines, where to find the nested arrays. If you have a plain nested array, just leave this out.
The key value
defines, which value to map to the size of the rectangles of the Treemap.
The key data
defines, which data to store. If omitted, the complete object or array branch is stored.
This might be the way to choose in most cases. That way you keep all the information accessible when drawing the treemap.
Parameters
data
(String | Number | Object | Array) – The data element (e.g. a String)keys
Object? – Which keys should be used to build the Treemap: e.g. {children:"items", value:"size", data:"name"}. See the example for different ways how to use that.
Returns Boolean – Returns true, if adding succeeded
Adds one element to the treemap. If there is already an item which has this value as data, just increase the counter of that item. If not, create a new Treemap with that data and init the counter with 1.
Parameters
data
(String | Number | Object | Array) – The data element (e.g. a String)keys
Array? – Ifkeys
is given, data has to be an object. It searches for the first key on the first level, for the second key on the second level, ...value
Number? – How much should this item add to the size. If not given, 1 is added.
Returns Treemap – Returns the treemap where the data was added
Set options for next calculation of the treemap. Currently there are the following options you might set:
- order: 'sort', 'shuffle' or 'keep'. Default is 'sort'. Attention: don't use 'keep' for the first calculation of the treemap.
- direction: 'both, 'horizontal' or 'vertical'. Default is 'both'.
- padding: 0 (default) or any positive number.
Parameters
options
Object – Object in the form{order: 'keep', padding: 4}
Calculates the rectangles of each item. While doing this, all counters and ignore flags are updated. If you have multiple values stored in your treemap you must give a key to define which value to use for calculation.
Parameters
key
String?
A simple recursive drawing routine. You have to supply a function for drawing one item. This function gets the actual item
as a parameter and has access to all the fields of that item, most important x
, y
, w
, and h
.
level
and depth
tells you, how deep this item is nested in the tree. The root node has level 0, an end node has depth 0. itemCount
gives you the number of items inside this item, counted recursively and the index
of item inside the parents sorted items array.
Example:
myTreemap.draw(function(item) {
let div = document.createElement('div');
div.style.left = item.x;
div.style.top = item.y;
div.style.width = item.w;
div.style.height = item.h;
document.body.appendChild(div);
});
Parameters
drawItemFunction
Function – A function that draws one item