ChrisCoray
ChrisCoray

Reputation: 455

d3.js Treemap - Is there a way to specify display preference (sorting)?

I'm working on a d3.js-based Treemap, http://mbostock.github.com/d3/ex/treemap.html, and I'm new to D3. Basically I have a list of values from a JSON file and am creating a basic one-parent treemap that displays the key in a box, size dependent on the value of the key.

The problem I'm running into that I'd like to solve is that my data tends to gravitate the high end toward the right, so all the big boxes end up there and all the small boxes end up on the left. In my mind (and the mind of the designer), since we read left to right, it would make more sense to have the larger boxes on the left, and the smaller boxes on the right. Obviously our dimensions don't need to change, just the order they are put in. See http://chrislcoray.com/browsertest/treemap_issue.jpg for how the data is currently displaying.

So for example, lets say my keys are tags in a blog page. My JSON (don't ask why I'm using JSON in a blog, its an example) might look something like this:

{
    "name": "tags",
    "children": [
        {"name":"cooking", "size": 35},
        {"name":"video games", "size": 31},
        {"name":"book club", "size": 26},
        {"name":"knitting", "size": 23},
        {"name":"hunting", "size": 22},
        {"name":"farming", "size": 19},
        {"name":"athletics", "size": 6},
        {"name":"toys", "size": 3},
        {"name":"sanitizer", "size": 3},
        {"name":"pigs", "size": 2},
        {"name":"ducks", "size": 2},
        {"name":"wildlife", "size": 2},
        {"name":"automobiles", "size": 1},
        {"name":"waterbottles", "size": 1},
        {"name":"telephone cords", "size": 1},
        {"name":"lampshade hats", "size": 1}
    ]
}

My D3 looks like this:

var jsonFeed = '/JSON/tags.json';

var width = jQuery('#container').width(),
    height = jQuery('#container').height();

var treemap = d3.layout.treemap()
    .size([width, height])
    .sticky(true)
    //.sort(0)
    .value(function(d) { return d.size; });

var div = d3.select('#container');

d3.json(jsonFeed, function(json) {
    div.data([json]).selectAll('div')
        .data(treemap.nodes)
    .enter().append("div")
        .attr("class", "cell")
        .call(cell)
        .text(function(d) { return d.children ? null : d.name; });
});

Based on this data, I would expect "Cooking" to take up a very large space on the left, but for some reason it is instead on the right. As you can see in the code, I've been playing with "sort" (commented out) but I still haven't figured out how to make it work properly.

Any advice/suggestions/etc. are greatly appreciated. :)

EDIT: Code consistency in keeping it generic

Upvotes: 3

Views: 4177

Answers (1)

Bill
Bill

Reputation: 25555

You can see a working example at http://jsfiddle.net/WYqRj/2/.

You were close, you just need to define the appropriate comparator function for sort. I implemented a simple one to sort in a descending manner.

var treemap = d3.layout.treemap()
    .size([width, height])
    .sticky(true)
    .sort(function(a,b) { return a.size - b.size; })
    .round(true)
    .value(function(d) { return d.size; });

Upvotes: 5

Related Questions