Question

I want to show the city name and population related to the voronoi area hovered over. However, with how I made the voronoi areas, I had to either only send coordinate data and have all of the drawings work, or send more data and none of the voronoi areas are drawn (b/c it can't read the non-coordinate data, and I don't know how to specify within an array or object, at least when creating voronois). I can enter static or irrelevant data for the tooltip (as I did below), but not anything from the actual dataset.

var tooltip = d3.select("body")
    .append("div")
    .style("position", "absolute")
    .style("z-index", "10")
    .style("visibility", "hidden")
    .text("a simple tooltip");

var voronoi = d3.geom.voronoi()
        .clipExtent([[0, 0], [w, h]]);

d3.csv("us-cities1.csv", function(d) {
    return [projection([+d.lon, +d.lat])[0], projection([+d.lon, +d.lat])[1]];
        }, function(error, rows) {
            vertices = rows;
            drawV(vertices);
            }
        );

function polygon(d) {
        return "M" + d.join("L") + "Z";
}

function drawV(d) {
    svg.append("g")
       .selectAll("path")
       .data(voronoi(d), polygon)
     .enter().append("path")
       .attr("class", "test")
       .attr("d", polygon)
       .attr("id", function(d, i){return i;})
       .on("mouseover", function(){return tooltip.style("visibility", "visible");})
       .on("mousemove", function(){return tooltip.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px").text((this).id);})
       .on("mouseout", function(){return tooltip.style("visibility", "hidden");});

    svg.selectAll("circle")
       .data(d)
     .enter().append("circle")
       .attr("class", "city")
       .attr("transform", function(d) { return "translate(" + d + ")"; })
       .attr("r", 2);
        }
Was it helpful?

Solution

I've put together an example using your data to demonstrate what Lars mentions. I created a variable for Voronoi like this:

var voronoi = d3.geom.voronoi()
    .x(function(d) { return (d.coords[0]); })
    .y(function(d) { return (d.coords[1]); });

which was taken from this Bl.ock by Mike. This allows you to specify the array of coordinates and still have them connected to the descriptive data you want to display.

I then created the object to store all the data in a format that could be used in the Voronio polygons using:

cities.forEach(function (d,i) {
    var element = { 
            coords: projection([+d.lon, +d.lat]),
            place: d.place,
            rank: d.rank,
            population: d.population
        };
    locCities.push(element);
});

I could have specified the translation of the coordinates in the voronio variable and then just used the cities variable, but I didn't.

The title attribute was used for the tooltips, but this can be replaced with something more appropriate such as what you have in your code. The relevant code is :

.append("title") // using titles instead of tooltips 
    .text(function (d,i) { return d.point.place + " ranked " + d.point.rank; });

There were a few issues with the data. I had to use an older version of d3 (3.1.5) to get the geojson to render correctly. I know there have been a number of chnanges to the AlberUsa projection so beware there is an issue there.

The location of some of the cities seems wrong to me for instance San Fancisco appears somewhere in Florida (this caused me some confusion). So I checked the original csv file and the coordinates seem to be wrong in there and the data is rendering where it should (just not where I'd expect according to the labels).

Now putting it all together you can find it here

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top