Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Re-render HTML after zoom using Dagre d3

Edit I have found a solution involving using a slightly older version of the dagre-d3 library (4.11). If anyone can find the problem with the latest version, that would help too. Thank you

I'm using Dagre d3 to draw some graphs.

When I initially render my graph, I do

g = new dagreD3.graphlib.Graph()
          .setGraph({})
          .setDefaultEdgeLabel(function() { return {}; });
var svg = d3.select("svg"),
            inner = svg.select("g");
            svgGroup = svg.append("g");
var render = new dagreD3.render();

        render(d3.select("svg g"), g);

        var zoom = d3.behavior.zoom().on("zoom", function() {
              inner.attr("transform", "translate(" + d3.event.translate + ")" +
                    "scale(" + d3.event.scale + ")");
              currentZoomScale = d3.event.scale;
              currentPosition = d3.event.translate;

            });
        svg.call(zoom);

Then, when a user clicks on a certain node, I want to append HTML to that node's label. This doesn't show unless I re-render the graph, which I do with the following:

g.node(id).label += "<div>" + inputTemplate + "</div>";

var zoom = d3.behavior.zoom()
        .scale(currentZoomScale)
        .on("zoom", function() {
        inner.attr("transform", "translate(" + d3.event.translate + ")" + "scale(" + d3.event.scale + ")")
                    });
        svg.call(zoom);

        d3.select("svg").on("dblclick.zoom", null);
        inner.attr("transform", "translate(" + currentPosition + ")" + "scale(" + currentZoomScale + ")");

I thought that by maintaining currentPosition and currentZoomScale I would be able to make sure the graph stays well after zooming and re-rendering. But this is not the case. All my nodes become smaller if I zoom out, and larger if I zoom in.

like image 974
db2791 Avatar asked Oct 22 '16 20:10

db2791


2 Answers

I'm not crystal clear on the problem but could it be because you have included .scale(currentZoomScale) in the second line of

var zoom = d3.behavior.zoom()
        .scale(currentZoomScale)
        .on("zoom", function() {
        inner.attr("transform", "translate(" + d3.event.translate + ")" + "scale(" + d3.event.scale + ")")
                    });
        svg.call(zoom);

        d3.select("svg").on("dblclick.zoom", null);
        inner.attr("transform", "translate(" + currentPosition + ")" + "scale(" + currentZoomScale + ")");

and then you're scaling it again in the innner.attr()?

like image 143
K Scandrett Avatar answered Nov 20 '22 19:11

K Scandrett


It seems to me that the problem lies here:

var svg = d3.select("svg"),
    inner = svg.select("g");
    svgGroup = svg.append("g");

If you look at the order of your code, there is no <g> when you define inner. So, at this point, inner is null. When you re-render the chart the group is now there, and inner is no more a null selection.

Thus, a possible solution is just changing the order:

var svg = d3.select("svg"),
    svgGroup = svg.append("g");//we first append the <g>..    
    inner = svg.select("g");//and only after that we select it
like image 33
Gerardo Furtado Avatar answered Nov 20 '22 19:11

Gerardo Furtado