Attaching data to voronoi areas, for display when hovered over

343 views
Skip to first unread message

Nick Silhacek

unread,
Jan 9, 2014, 3:31:22 PM1/9/14
to d3...@googlegroups.com
I've made a map of the US with some major cities drawn on the map, and voronoi areas created based on those cities. Now what I want to do is have some relevant information displayed when I hover over an area. Unfortunately, I think the way I approached getting the data to make the polygons (see highlighted line) is making it difficult or impossible for me to get to the other information. Any suggestions? Copies of relevant files are attached, as well.


// Create the projection type
var projection = d3.geo.albersUsa() 
.translate([w/2, h/2]) 
.scale([1080]);

// Define default path generator
var path = d3.geo.path()
.projection(projection);
// CANVAS STUFF
// Create the SVG element
var svg = d3.select("body").append("svg")
.attr("width", w)
.attr("height", h); 

// Append the background to the SVG
svg.append("rect")
.attr("class", "background")
.attr("width", w)
.attr("height", h)

// Append a group element to the SVG (holds everything from the map)
var g = svg.append("g");
// VORONOI STUFF
// Creating the voronoi layout
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;
  console.log(vertices);
  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);

        svg.selectAll("circle")
           .data(d)
          .enter().append("circle")
          .attr("class", "city")
           .attr("transform", function(d) { return "translate(" + d + ")"; })
           .attr("r", 2);
       }
// MAP STUFF
// Loading state boundaries GeoJSON data
d3.json("us-states.json", function(error, us) {
g.append("g")
.attr("id", "states")
.selectAll("path")
.data(us.features) 
.enter().append("path") 
.attr("d", path); 
});

// JQUERY
$(document).ready(function () {
   $("path.test").hover
    (function () {
       $("#label").addClass("states");
    }, function() {
    $("#label").removeClass("states");
    }
   );
});
voronoi_info_us_map_test1.html
us-cities1.csv
us-states.json
Message has been deleted

Mihai Badescu

unread,
Jan 9, 2014, 3:52:00 PM1/9/14
to d3...@googlegroups.com
I recently found out about implementing a tooltip using title attribute. However I took the route outlined here where a tooltip div is generated first, and you bind mouseover mousemove and mouseout listeners to your object.
If I'm reading this correctly you want to hover the voronoi areas to pull up city info. In which case you would have something like

...
svg.append("g")
   .selectAll("path")
   .data(voronoi(d), polygon)
   .enter().append("path")
   .attr("class", "test")
   .attr("d", polygon)
.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");})
.on("mouseout", function(){return tooltip.style("visibility", "hidden");});
...

Nick Silhacek

unread,
Jan 9, 2014, 4:11:25 PM1/9/14
to d3...@googlegroups.com
Thanks a lot for the display suggestion. That's half of my trouble. The other half is that I can't figure out how to get the information I want to pop up (e.g., the name and population of the city in the area over which I'm hovering).

Mihai Badescu

unread,
Jan 9, 2014, 4:30:39 PM1/9/14
to d3...@googlegroups.com
This is how I've implemented it in the past..I have a data attribute for each of the nodes in which HTML is generated before setting the mouse events. And on mouse over I grab that HTML and fill the tooltip with it.

      .attr("data", function(d) {   return  "<p>" +
                                            "<b>" + d.Name + "</b>" + "</br>" +
                                            "<b>" + "Price: " + "</b>" + numberFormat(d.Price) + "</br>" +
                                            "</p>"
                                    })

      .on("mouseover", function(){
          d3.select("#tooltip").html(this.getAttribute("data"))
          return tooltip.style("visibility", "visible");
        })
      .on("mousemove", function(){
          return tooltip.style("top", (d3.event.pageY-150)+"px")
                      .style("left",(d3.event.pageX+20)+"px");

Nick Silhacek

unread,
Jan 17, 2014, 1:35:39 PM1/17/14
to d3...@googlegroups.com
For anyone interested, here's an answer to my problem on StackOverflow. It turns out that my main problem was that I was trying to use the voronoi .x and .y functions in the wrong place (when I was making the cells, not when creating the voronoi variable). There were great answers to the problem of the display part itself both in the group and on Stack.

Allison McCann

unread,
Apr 18, 2014, 5:00:28 PM4/18/14
to d3...@googlegroups.com
Hey Nick, 

Saw your post over on StackOverflow and I think I'm running into a similar issue. Except that my information only displays when hovering on the edges of the voronoi polygons, not inside them. I saw that someone responded to use an older version of d3, as well as weird changes to the albers projection. Did you end up reverting to an older version of d3 too? Seems odd. 

Thanks, 
Allison 

Philip Pedruco

unread,
Apr 19, 2014, 6:12:30 PM4/19/14
to d3...@googlegroups.com
Hi Allison,

I think that Nick's problem was essentially solved in the SO comments and answers.  If you've got a similar but different problem it would be worth posting a new question on SO together with the relevant code, it seems to be pretty active over the break so you're likely to get a quick answer!

Cheers

Phil

Nick Silhacek

unread,
May 2, 2014, 2:10:55 PM5/2/14
to d3...@googlegroups.com
Hi Allison,

My problem really hinged on the fact that I misunderstood where to specify the .x and .y accessor functions. There is no need to use an older version of d3. For me, the API just didn't make sense to me, but once I found a couple proper examples, plus the advice I got on SO, I was able to solve the issue.

Are you still having issues?

Nick
Reply all
Reply to author
Forward
0 new messages