0

I am trying to conditionally change the background of some circles created with D3 but I am unable to get the if else logic to correctly pick out the correct picture. The code goes right to the final else statement for the default.gif. I don't see any errors in the console. All the images are in the same directory as the html file.

var diameter = 500, //max size of the bubbles
    format   = d3.format(",d"),
    color    = d3.scaleOrdinal(d3.schemeCategory20c); //color category

var bubble = d3.pack()
    .size([diameter, diameter])
    .padding(1.5);

var svg = d3.select("body")
    .append("svg")
    .attr("width", diameter)
    .attr("height", diameter)
    .attr("class", "bubble");

d3.csv("fruit.csv", function(error, data){
    if (error) throw error;

    //convert numerical values from strings to numbers
    data = data.map(function(d){ d.value = +d["Amount"]; return d; });

    //Sets up a hierarchy of data object
    var root = d3.hierarchy({children:data})
      .sum(function(d) { return d.value; })
      .sort(function(a, b) { return b.value - a.value; });

    //Once we have hierarchal data, run bubble generator
    bubble(root);

    //setup the chart
    var bubbles = svg.selectAll(".bubble")
        .data(root.children)
        .enter();

    //create the bubbles
    bubbles.append("circle")
        .attr("class", "circle")
        .attr("r", function(d){ return d.r; })
        .attr("cx", function(d){ return d.x; })
        .attr("cy", function(d){ return d.y; })
        .append("defs")
        .append("pattern")
        .append("image")
        .attr("xlink:href", function(d) {
            if ( d.Fruit == "Apple") {
                return "apple.jpg";
            }
            else if (d.Fruit == "Pear") {
                return "pear.jpg"
            }
            else if (d.Fruit == "Banana") {
                return "banana.jpg";
            }
            else if (d.Fruit == "Strawberry") {
                return "strawberry.jpg";
            }
            else if (d.Fruit == "Grapes") {
                return "grapes.jpg";
            }
            else { return "default.gif"; }
        });
        //.style("fill", function(d) { return color(d.value); });

    //format the text for each bubble
    bubbles.append("text")
        .attr("x", function(d){ return d.x; })
        .attr("y", function(d){ return d.y + 5; })
        .attr("text-anchor", "middle")
        .text(function(d){ return d.data["Fruit"]; })
        .style("fill","white")
        .style("font-family", "Helvetica Neue, Helvetica, Arial, san-serif")
        .style("font-size", "12px");
});

The csv file contains the following data: Fruit,Amount Apple,32 Pear,13 Banana,25 Grapes,29 Strawberry,36

Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171
charlie
  • 187
  • 4
  • 15
  • I'm surprised that you're seeing any image at all! Are you really seeing `default.gif` as the circles' background? – Gerardo Furtado Sep 17 '17 at 11:53
  • edited the code to reflect d.data.Fruit but still no images – charlie Sep 17 '17 at 15:20
  • Please read the first paragraph of my answer. – Gerardo Furtado Sep 17 '17 at 21:59
  • don't keep editing your question to add a proposed code and then making further questions. This not only is confusing, but also renders the answer useless, which is quite rude with people trying to help you. The issue with your if statement is clear, I explained it. You have other problems, specifically with your defs/patterns. Please, for solving further issues, post **another question**. I just rolled back your question. Alternatively, if you don't want to post a new question, just let me know and I'll delete my answer and roll back your question to the original, as if nothing had happened. – Gerardo Furtado Sep 18 '17 at 06:40

1 Answers1

0

As I said in my comment, I'm surprised that you're seeing anything as the circles' background, since your code for creating/referencing the patterns is not correct. For a quick explanation, check my answer here.

However, I'll address only your main question here, which is the if statement.

The problem is that you're using d3.hierarchy to create your data array. Because of that, all data are inside node.data. According the API:

The returned node and each descendant has the following properties:

  • node.data - the associated data, as specified to the constructor.

Therefore, for your conditionals, instead of:

d.Fruit == "Apple"

It should be:

d.data.Fruit == "Apple"

And the same for d.data.Fruit == "Pear", d.data.Fruit == "Banana" etc...

Community
  • 1
  • 1
Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171
  • Thanks Gerardo. I edited it to d.data.Fruit but it shows black background image. The default image for the else section is also a black image so I thought that was the image being displayed. But, I remembered after reading your post that the default color of svg circles are all black. When I check the html elements in chrome developer tools and hover over the element I can see the image but it doesn't show in the browser window. – charlie Sep 17 '17 at 14:25
  • Yes. Thanks. I edited the code to reflect what read from the answer you gave elsewhere. I get d.data.Fruit undefined. – charlie Sep 18 '17 at 03:32
  • @charlie Since now you're using `data` and not `root`, as in your first edit, it has to be `d.Fruit` and not `d.data.Fruit`. That's the problem of editing the code of a question for something else, it is confusing, and the valid answer becomes wrong. – Gerardo Furtado Sep 18 '17 at 04:21