Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getBBox of selection with D3 v4

Tags:

d3.js

I tried using d3.legend.js with d3 v4 but ran into a problem. So I ported index.html to use d3 v4 to see if the problem was in my code or in d3.legend.js. See my gist (running version) - the problem is at line 47 of d3.legend.js Uncaught TypeError: Cannot read property '0' of undefined.

I'm not that familiar with d3 (or the changes from v3) to understand how to fix this error -- any ideas?

UPDATE 1: This appears to have something to do with the way d3 selections have changed, per the release notes.

But still not sure how to access the getBBox() method from the li Selection.

UPDATE 2: li.node().getBBox() works if li is non-null. For some reason code like

var li = g.selectAll(".legend-items")
             .data(["g"])
           .enter()
             .append("g")
             .attr("class", "legend-items")

leaves li as null if the class already exists.

I was forced to use the (somewhat inelegant)

var licreate = g.selectAll(".legend-items")
        .data(["g"])
      .enter()
        .append("g")
        .attr("class", "legend-items");
var li = g.selectAll(".legend-items");
like image 581
Lou K Avatar asked Aug 04 '16 18:08

Lou K


People also ask

What is a d3 selection?

Selections allow powerful data-driven transformation of the document object model (DOM): set attributes, styles, properties, HTML or text content, and more. Using the data join's enter and exit selections, you can also add or remove elements to correspond to data.

What do the select () and selectAll () functions in d3 do?

select selects the first matching element whilst d3. selectAll selects all matching elements. Both functions take a string as its only argument. The string specifies which elements to select and is in the form of a CSS selector string (e.g. div.


1 Answers

This question was posted in the first days of D3 v4, and it uses a D3 plugin from 2012, way before v4 (and actually before v3 as well).

The necessary changes here are two:

  1. In D3 v4 selections are not arrays, but objects instead. Therefore, using [0][0] won't work here. It should use node() instead:

    var lbbox = li.node().getBBox()
    
  2. In D3 v4 the "enter" selection doesn't magically change the "update" selection anymore. Therefore, it should be:

    lb = lb.enter().append("rect").classed("legend-box",true).merge(lb);
    li = li.enter().append("g").classed("legend-items",true).merge(li);
    

    Also, as I can't see an update situation for the "update" selection, I suggest that you use a simple "enter" selection here.

Here is the updated bl.ocks: http://bl.ocks.org/GerardoFurtado/raw/ca06385c40afa5414830b3d3d449cbe5/efeeed6ffc42051f433cfcb54c462acfd0daebb5/

like image 54
Gerardo Furtado Avatar answered Oct 21 '22 17:10

Gerardo Furtado