0

I'm trying to set x and y of svg path elements using the D3 framework. I have written this code to add the source/target nodes for each path:

link.enter().insert("path", "g")
            .attr("class", "link")
            .attr("d", function (d) {
                console.dir(d);
                var s = {
                    x: d.source.x0,
                    y: d.source.y0
                };
                var t = {
                    x: d.target.x0,
                    y: d.target.y0
                };

                console.log("tx0: " + d.target.x0 + "; ty0: " + d.target.y0);
                console.dir(t);
                console.log("sx0: " + d.source.x0 + "; sy0: " + d.source.y0);
                console.dir(s);
                //console.dir(o);
                return diagonal({
                    source: s,
                    target: t
                });
            });

When I run it, I get the following console log output:

enter image description here

Can somebody explain why the values of the properties x0 and y0 in the object output are different to those that are logged next, and why the target properties are undefined?

Edited I edit this d3 example and use Chrome

Kamerton
  • 315
  • 3
  • 9
  • you haven't run the simulation yet. This is the code you need to add in the `tick` callback. I don't see the need for the `g` in the `insert()` call. You get undefined because `d.target` is **not** an object. – rioV8 Sep 12 '18 at 15:49
  • 1
    See https://stackoverflow.com/questions/11954152/whats-the-difference-between-console-dir-and-console-log – i alarmed alien Sep 12 '18 at 16:02
  • @rioV8 About what simulation did you spoke? If `d.target` is not an object what is it? – Kamerton Sep 13 '18 at 07:49
  • the force simulation, the first tick it will modify the links objects and substitute the string references with object references – rioV8 Sep 13 '18 at 08:09
  • @rioV8 There is no the force simulation in my case. All d3.js tree examples that i found use the single `udate(source)` function that called manualy. Does it run behind the scene always? – Kamerton Sep 13 '18 at 10:49
  • I have been trying to recreate your issue using the .block you linked to, but can't. Can you link to a working version of it? The link code that you're using is a weird mix of the standard `enter` selection link positioning code and the `update` selection link code. – i alarmed alien Sep 13 '18 at 10:55
  • rioV8's comments seem to be directed at some other question, not this one. – i alarmed alien Sep 13 '18 at 10:56
  • @ialarmedalien in the initial question there was no mentioning of where this code was used and it looks like the code for a force sim link update, apart from the `insert()`. – rioV8 Sep 13 '18 at 11:56
  • @rioV8 [Here](https://jsfiddle.net/3bvrmhwy/9/) is the full html. The problem region is on 522 row. – Kamerton Sep 13 '18 at 13:02
  • @rioV8 it's better not to make assumptions about what people are trying to do--if you are wrong, you will just end up confusing them (see above for an example). – i alarmed alien Sep 13 '18 at 13:25
  • 1
    @AlexeyKubasov your fiddle is not functional -- [here](https://jsfiddle.net/3bvrmhwy/14/) is a working version. – i alarmed alien Sep 13 '18 at 13:26

1 Answers1

1

The reason for the seemingly odd results is that you are trying to access properties that don't exist. If you look at the error console, you'll see that there are five errors of the form:

Error: Problem parsing d="M0,400CNaN,400 NaN, ,"

If you step through your code in a debugger, you'll find that the target link does not have x0 and y0 set yet, so that's why tx0 and ty0 are coming up as undefined. Why is this? If you look through the code, node.x0 and node.y0 are set in two places; first, the root node has these two properties set before the tree drawing code is run:

    root = treeData;
    root.x0 = viewerHeight / 2;
    root.y0 = 0;

and after the chart has been drawn, this code is run to add x0 and y0 to all nodes:

    nodes.forEach(function (d) {
        d.x0 = d.x;
        d.y0 = d.y;
    });

If a node is newly added to the chart, it will not have x0 and y0 set, whereas if it has been displayed before, hidden, and then redisplayed (e.g. when you collapse a parent node and then expand it), x0 and y0 will already have been defined so there's no error or undefined target node properties. The five links that are created when the tree is drawn for the first time all have x0 and y0 set for the source node, because it is the root variable here:

    root = treeData;
    root.x0 = viewerHeight / 2;
    root.y0 = 0;

but the target nodes won't have x0 and y0 set until after everything has been drawn and this code is run:

    nodes.forEach(function (d) {
        d.x0 = d.x;
        d.y0 = d.y;
    });

The difference between what you see from your console.log statements and the console.dir statements is due to the console.log statements evaluating the status of the object when the code is run vs. the console.dir statements, which give access to the object in its current state. See What's the difference between console.dir and console.log? for more information.

i alarmed alien
  • 9,412
  • 3
  • 27
  • 40
  • Thanks a lot! I realy forgot about dynamic properties creation in js. But can you explain the _current_ state of object for `.dir()`? I have read the linked question but not found it. I suposed that curent is when i call the output, does it? I cant realize what difference between _"when code is run"_ and _"object curent state"_. Curent state is when i run. Or not? – Kamerton Sep 13 '18 at 15:10