Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Appending multiple svg text with d3

Tags:

svg

d3.js

I have been stuck on this problem for days.

So I have a dataset of objects of the following form:

dataset = [{metric:"revenue",value:0.03},{metric:"sales", value:0.15},{metric:"churn", value: 0.06},{metric:"logins", value: 0.45}]

The following code would display the 4 metric names in a grid pattern (meshy, meshx are the coordinates points of the grid and meshsize is the size of the grid, so this is just putting the text in the middle of a grid square):

svg.selectAll("text")
    .data(dataset)
    .enter()
    .append("text")
    .text(function(d){
        return d.metric;
    })
    .attr("y",function(d,i){
        return meshy[i] + meshsize/2;
    })
    .attr("x", function(d,i){
        return meshx[i] + meshsize/2;
    })
    .attr("font-size",25)
    .attr("font-family","serif")
    .attr("text-anchor","middle")
    .attr("font-weight","bold");

Now I would like to put the value of the metric right underneath the metric name like so:

 svg.append("text")
    .data(dataset)
    .text(function(d){
        return (d.value);
    })
    .attr("y",function(d,i){
        return meshy[i] + meshsize/2 + 20;
    })
    .attr("x", function(d,i){
        return meshx[i] + meshsize/2 ;
    })
    .attr("font-size",25)
    .attr("font-family","serif")
    .attr("text-anchor","middle")
    .attr("font-weight","bold");

But this only returns the value underneath the metric name for the FIRST metric, the other 3 value texts are not even in the DOM. I have tried multiple approaches including replacing .text with .html as described here:https://github.com/mbostock/d3/wiki/Selections#wiki-html with no success. I have also tried appending paragraph elements instead - this works but the p elements are positioned below the svg body in a list with no obvious way to move them into the right position. The code above is the closest I have come to getting what I need, but for some reason only the first value text shows up. However, I am open to any approach in d3 that gets the job done: 4 metric names with the values right underneath them

like image 523
user1452494 Avatar asked Jul 01 '13 17:07

user1452494


People also ask

Can we group SVG elements in d3js?

The <g> SVG element is a container used to group other SVG elements. Transformations applied to the <g> element are performed on its child elements, and its attributes are inherited by its children. We can create a group element with D3. js by appending a g element using any selection.

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

d3. select selects the first matching element whilst d3. selectAll selects all matching elements. Both functions take a string as its only argument.

Which tag is used for marking points in D3 using SVG?

Points in D3 using SVG For points, you can use the circle tag. As you can see on the following example, the circle position and radius is controlled by the cx , cy , r attribues.

How to create SVG using D3?

To create SVG using D3. js, let us follow the steps given below. Step 1 − Create a container to hold the SVG image as given below. Step 2 − Select the SVG container using the select() method and inject the SVG element using the append() method.


1 Answers

In your second block of code, you are only appending one text element, hence only one of them is appearing. What you need to do is to append the text similar to your first block, i.e. with the .enter() selection. For this, you have two choices. You can either save and reuse the .enter() selection, or assign different classes to the two kinds of text to be able to distinguish between them.

Option 1:

var texts = svg.selectAll("text")
                .data(dataset)
                .enter();

texts.append("text")
     .text(function(d){
                    return d.metric;
                })
     // set position etc.

texts.append("text")
     .text(function(d){
                    return d.value;
                })
     // set position etc.

Option 2:

svg.selectAll("text.title")
                .data(dataset)
                .enter()
                .append("text")
                .attr("class", "title")
                .text(function(d){
                    return d.metric;
                })
     // set position etc.

svg.selectAll("text.value")
                .data(dataset)
                .enter()
                .append("text")
                .attr("class", "value")
                .text(function(d){
                    return d.value;
                })
     // set position etc.

The first option is obviously shorter, but depending on what else you want to do, the second option may be preferable -- if you want to modify the text afterwards, it will be a lot easier if you can distinguish between the two kinds of text. You can also use the different classes to give different CSS styles.

like image 51
Lars Kotthoff Avatar answered Nov 30 '22 06:11

Lars Kotthoff