Re-render HTML after zoom using Dagre d3
Asked Answered
L

2

7

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.

Likeness answered 22/10, 2016 at 20:24 Comment(1)
What do you mean by 'stays well'?Gerah
G
1

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()?

Gerah answered 24/10, 2016 at 22:4 Comment(0)
P
1

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
Punk answered 25/10, 2016 at 3:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.