Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
885 views
in Technique[技术] by (71.8m points)

d3.js - D3 conditionally append image OR circle element based on variable

I have a D3 scatter chart and I'm trying to add the option to view the chart as circles or as images, based on the value of a variable.

At the moment I can view the chart as either (as long as I comment one of them out)

Here is the code for appending the images:

   svg.selectAll(".image")
  .data(data)
  .enter()
  .append("svg:image")
  .attr("x", xMap)
  .attr("y", yMap)
  .attr("width", logosize)
  .attr("height", logosize)
  .attr('transform', function(d) { return 'translate('+ -d.logosize/2 +',' + -d.logosize/2 + ')'; }   )
  .attr("xlink:href", function(d) {
    return d.brand_image;
  })

and the code for appending the dots:

svg.selectAll(".dot")
  .data(data)
  .enter().append("circle")
  .attr("class", "dot")
  .attr("r", 3.5)
  .attr("cx", xMap)
  .attr("cy", yMap)
  .style("fill", function(d) {
    return color(cValue(d));
  })

The variable is var displaytype = "image" // or "dot"

I was trying to do something like:

    if (displaytype == "image") { return 
    
    //....code for images.....
    
    else    { return  
    
    
   //....code for dots.....
    
    }

Any help on trying to figure this out would be much appreciated

Thanks

question from:https://stackoverflow.com/questions/65849641/d3-conditionally-append-image-or-circle-element-based-on-variable

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Your approach of using if/else is not wrong. What you need to keep in mind is that dots and images are equivalent representations of what I'll call "points". This means that the selection shouldn't distinguish circles from images: it should just select points. This could be done by using a class selector instead of a tag selector.

In your case, the code is using two different class selectors: .dot and .image. Instead of svg.selectAll('.image') and svg.selectAll('.dot'), you could use svg.selectAll('.point') for both of them. Thus:

    const enterSelection = svg.selectAll(".point").data(data).enter();
    
    if (displaytype == "image") {
      enterSelection
        .append("svg:image")
        .attr("class", "point")
        .attr("x", xMap)
        .attr("y", yMap)
        .attr("width", logosize)
        .attr("height", logosize)
        .attr("transform", function (d) {
          return "translate(" + -d.logosize / 2 + "," + -d.logosize / 2 + ")";
        })
        .attr("xlink:href", function (d) {
          return d.brand_image;
        });
    } else {
      enterSelection
        .append("circle")
        .attr("class", "point")
        .attr("r", 3.5)
        .attr("cx", xMap)
        .attr("cy", yMap)
        .style("fill", function (d) {
          return color(cValue(d));
        });
    }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...