estebanpdl
estebanpdl

Reputation: 1233

Back to path style color on click in d3.select(this)

I have a function in a d3.js map.

I used d3.select(this).style('fill', 'red'); in order to change color when user clicks on svg path.

The color changes, but I want to update the svg path color to the older one when I click on a new path.

This is the function I used:

.on('click', function(d) {
        d3.select(this).style('fill', 'red')
            .style('stroke-width', 3);
        var year = $(".year-label").text();
        var infoYear = 'yr' + year;
        var counts = [];
        for (i = 1984; i <= 2016; i++){
            cnts = 'yr' + i.toString();
            counts.push(d.properties[cnts]);
        }
        console.log(counts);
        console.log(counts.length);

        $('.text-name').empty();
        var nameit = d.properties.city;
        $('.text-name').append(nameit);
});

Each path has a unique id. So I tried this function with no results:

.on('click', function(d) {
    d3.select('._' + d.geoid).this.style('fill', 'red');

I'm missing an element, so I'm trying to solve it with littles changes on that line. However, it doesn't work well.

This is an image of this issue:

enter image description here

Thanks in advance for your support!

Upvotes: 4

Views: 1855

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102188

There are several ways for reverting the colour of the previously clicked path. But the most important question is: how was that colour set in the first place?

For instance, if all the paths have a gray fill and only the clicked one have a red fill, you could simply write this (lazy) code:

d3.selectAll("path").style("fill", "gray")
d3.select(this).style("fill", "red")

Something like this:

var data = d3.range(4);
var svg = d3.select("body")
  .append("svg")
  .attr("width", 400)
  .attr("height", 100);

var circles = svg.selectAll(".circles")
  .data(data)
  .enter()
  .append("circle");

circles.attr("cy", 50)
  .attr("r", 50)
  .attr("cx", function(d){ return 50 + d*100})
  .attr("fill", "gray")
  .attr("cursor", "pointer");

circles.on("click", function(){
  d3.selectAll("circle").attr("fill", "gray");
  d3.select(this).attr("fill", "red");
});
<script src="https://d3js.org/d3.v4.min.js"></script>

If, on the other hand, their colours depend on the data, you could save the last clicked path and set the colour again inside the clicked function.

Since I don't know how you fill the other paths, this is another snippet showing how to save the previous colour and retrieving it in the next click. In this snippet, each circle has a random color. When you click it, it becomes red, but before becoming red it saves the clicked element and its colour:

prevElem = d3.select(this);
prevColour = d3.select(this).attr("fill");

Then, when you click another circle, it returns this previously clicked circle to the previous colour:

if(prevElem){prevElem.attr("fill", prevColour);};

Check the snippet:

var data = d3.range(4);
    var svg = d3.select("body")
      .append("svg")
      .attr("width", 400)
      .attr("height", 100);

var prevElem, prevColour;

    var circles = svg.selectAll(".circles")
      .data(data)
      .enter()
      .append("circle");

    circles.attr("cy", 50)
      .attr("r", 50)
      .attr("cx", function(d){ return 50 + d*100})
      .attr("fill", function() {
    return "hsl(" + Math.random() * 360 + ",100%,50%)";
    })
      .attr("cursor", "pointer");

    circles.on("click", function(){
      if(prevElem){prevElem.attr("fill", prevColour);};
      prevElem = d3.select(this);
      prevColour = d3.select(this).attr("fill");
      d3.select(this).attr("fill", "red");
    });
<script src="https://d3js.org/d3.v4.min.js"></script>

Upvotes: 4

Related Questions