javascriptsortingd3.jsgeospatialcircle-pack

geographic sort function for d3's pack layout


Using d3's pack layout, I made some bubbles associated with states. Current test script: https://jsfiddle.net/80wjyxp4/4/. They're colored according to region. You'll note Texas is in the "NW", California in the "SE", etc.

Question:

How would you geographically sort the circles in pack-layout?

One hack way might use the default d3.layout.pack.sort(null). This sort starts with the first data point (in this case, AK) and then adds bubbles in a counterclockwise direction. I could hand-sort data to be input in an order that approximates state positions, and add in blank circles to move edge circles around.

I'm interested about better ideas. Would it be better to use a modified force layout, like http://bl.ocks.org/mbostock/1073373? The d3.geom.voronoi() seems useful.

enter image description here


Solution

    1. Started with pack layout, to get circle radii
    2. used state centroids from this modified force layout http://bl.ocks.org/mbostock/1073373
    3. Contrived to avoid overlaps using collisions https://bl.ocks.org/mbostock/7881887

    The code is here: https://jsfiddle.net/xyn85de1/. It does NOT run because I can't get data for the topojson file, at http://bl.ocks.org/mbostock/raw/4090846/us.json, from the link, and the file is too large to copy-paste. Download to your own server then run.

    It has a hover-title text and transitions in, but ends up looking like this:

    bubbles

    Spacing and stuff is modifiable with different parameters. The circles are approximately sorted geographically. MO is that big gold one in the middle; AK and HI are dark blue to the left; CA is lower left in pink; TX is at the bottom in light blue. And so on. Code: After collecting all data (location data for init position of circles), along with the state name, value, area (for color coding) into the nodes variable:

    // circles
    var circles = svg.selectAll("g") //g
        .data(nodes)
        .enter()
        .append("g")
        .attr("transform", function(d) {
            return "translate(" + -d.x + "," + -d.y + ")";
        })
        .append("circle")
        .attr("transform", function(d) {
            return "translate(" + d.x + "," + d.y + ")";
        })
        .attr("r", function(d) {return d.r;})
        .attr("fill", function(d) { return color(d.area); })
        .call(force.drag); // lets you change the orientation
    
    // title text
    circles.append("title")
        .text(function(d) { return d.state + ": " + format(d.value) + " GWh"; });
    
    // // text // doesn't work :/ porque?
    // circles.append("text")
    //     .attr("dy", ".3em")
    //     //.style("text-anchor", "middle")
    //     .text(function(d) { return d.state.substring(0, d.r / 3); });
    
    // circle tick function
    function tick(e) {
        circles
            .each(collide(collision_alpha))
            .attr("cx", function(d) { return d.x; })
            .attr("cy", function(d) { return d.y; });
    }
    
    // force
    force.nodes(nodes)
        .on("tick", tick)
        .start();