-1

I have the following function that is called whenever a text element is clicked. Once called, it selects an element via id, and then changes its opacity to either 0 or 1.

d3.select("#viz").selectAll("text").on("click", function() {

      selectedCandidate = d3.select(this).attr("id").split(",")[0];
      selectedColor = d3.select(this).attr("id").split(",")[1];

      // determine if the line with same id as the text is visible
      var active   = document.getElementById(selectedCandidate).active ? false : true,
      newOpacity = active ? 0 : 1;
      newColor = active ? "gray" : selectedColor;
      // hide or show the elements
      d3.selectAll("#"+selectedCandidate)
        .style("opacity", newOpacity);
})

That works exactly as expected. I now want to add in a transition so the opacity change is gradual. I expected the solution to look something like this:

// hide or show the elements
      d3.select("#"+selectedCandidate)
        .transition()
        .duration(3000)
        .style("opacity", newOpacity);

And that works in the console as expected, but inside the function, it stops working altogether. Instead, the opacity just stops changing when the function is evoked.

Oliver G
  • 1,021
  • 2
  • 9
  • 20
  • I posted a working example below, but may not fully understand your question. One of the things I'd watch out for is using `selectAll` to select elements by ID. [Each element in your HTML document should have a unique ID](https://stackoverflow.com/questions/5611963/can-multiple-different-html-elements-have-the-same-id-if-theyre-different-eleme). If you really have multiple elements with the same ID, I'd suggest switching to class (or another attribute) instead. – mdml Jul 28 '19 at 13:15
  • I just changed it to 'select' rather than 'selectAll', as everything does indeed have a unique ID. Unfortunately the transition still isn't working. – Oliver G Jul 28 '19 at 17:34

1 Answers1

-1

We can not fully test your code, as we don't know the structure of the text elements inside your svg.

I am thinking that it stops working because maybe you are not updating the active attribute?

How about something like this? I have created a similar scenario and it seems to do what you need.

So having this HTML:

<body>
  <div class="container">
    <div>
      <svg id="viz" width="500" height="500">
        <text id="text1" x="10" y="20" active="0" >Text 1</text>
        <text id="text2" x="10" y="50" active="0" >Text 2</text>
        <text id="text3" x="10" y="80" active="0" >Text 3</text>
      </svg>
    </div>
  </div>
</body>

And your click function working like this:

d3.select("#viz").selectAll("text").on("click", function() {

  selectedCandidate = d3.select(this).attr("id").split(",")[0];
  selectedColor = d3.select(this).attr("id").split(",")[1];

  // determine if the line with same id as the text is visible
  var active = d3.select("#"+selectedCandidate).attr('active') === "0" ? true : false;

  newOpacity = active ? 0 : 1;
  newActive = active ? 1 : 0;

  // hide or show the elements
  d3.select("#"+selectedCandidate)
    .attr("active", newActive)
    .transition()
    .duration(500)
    .style("opacity", newOpacity);
})

Should be enough to toggle the text opacity.

Guillermo
  • 1,054
  • 2
  • 9
  • 12