Need another help to show up text on the screen dynamically

Now i got this second problem using d3.js that i cannot solve by my own. I got a dynamic array "path" which length always changes when i click on. Then i got a "text" variable at a starting position on the svg (112, 490). With the help of you guys, i now use the for-loop to show the names of the "path" array based on it's switching length on the console and it worked. But now i want the names to appear on the screen. But my

 textNode.attr("dx", 112 + i*2);

line does not work. I want the text shift right on the x-scale starting at the point 112 a little bit with each node.

This is the text

var text = svg.append("text")
.attr("dx", 112)
.attr("dy", 490)
.text("1. Node: " )

and this is the for loop

for (var i=0;i<path.length;i++) {
text.attr("dx", 112 + i*2);
text.text( +i+1+". Node: " + path[i].name);

Answers:

Answer

A very basic principle in D3: don't use loops, such as a for loop, to show or display the data (sometimes we do use loops, but in very specific and complex situations, not this one). In your other question, the proposed solution used loops because there was no d3.js tag in the question. But using a loop like this makes little sense if you're using D3. It's an entire library created to manipulate data, and you're ignoring its most important aspect.

Instead of that, bind your data to a selection. In your case, as your array is constantly changing, you're gonna need an "enter", "update" and "exit" selections.

First, bind your data:

var texts = svg.selectAll(".texts")
    .data(data);

Then, set the selections:

textsExit = texts.exit().remove();

textsEnter = texts.enter()
    .append("text")
    .attr("class", "texts");

textsUpdate = texts.merge(textsEnter)
    .attr("x", 10)
    .attr("y", (d, i) => i * 16)
    .text(d => d.name);

Here is a demo to show you how it works. I have an data array, which length changes every second:

var svg = d3.select("body").append("svg");

var dataset = [{
    name: "foo"
}, {
    name: "bar"
}, {
    name: "baz"
}, {
    name: "lorem"
}, {
    name: "ipsum"
}, {
    name: "dolot"
}, {
    name: "amet"
}];

print(dataset);

setInterval(()=> {
    var data = dataset.slice(Math.random() * 6);
    print(data);
}, 1000);

function print(data) {

    var texts = svg.selectAll(".texts")
        .data(data);

    textsExit = texts.exit().remove();

    textsEnter = texts.enter()
        .append("text")
        .attr("class", "texts");

    textsUpdate = texts.merge(textsEnter).attr("x", 10)
        .attr("y", (d, i) => 20 + i * 16)
        .text((d,i) => "Node " + (i+1) + ", name: " + d.name);

}
<script src="https://d3js.org/d3.v4.min.js"></script>

Answer

Not sure if this is incorrect for your specific use case, but I think you want to do "x" instead of "dx". That's how I've moved objects to the left / right in d3.js:

textNode.attr("x", 112 + i*2);

EDIT: here's an example that adds text objects and moves them to the right based on the index:

for (var i = 0; i < path.length; i++) {
    var text = svg.append("text")
        .attr("x", 112 + i*2)
        .attr("y", 490)
        .text("1. Node: " )
}

EDIT2: See Gerardo's answer. D3js has its own methods for binding and looping through data.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.