1
votes

I am trying to get lines to change style on mouseover across multiple charts. In this example available here, I have two charts that both have five groups A,B,C,D,E. Each however is in a different csv (I am open to bringing the data in one csv or as one json array, but this is just how I have it set up right now).

I can get two charts each with five lines corresponding to the group. Using the below code, I get the hovered over line to change style whilst fading out the other lines in that chart.

  // Fading and Selecting Lines
d3.selectAll('path.line.mainline')
    .on("mouseover", function(d) { 
    var HoveredLine = this;
     d3.selectAll('path.line.mainline').transition().duration(0)
       .style('opacity',function () {
       return (this === HoveredLine) ? 1.0 : 0.1;
    })
      .style('stroke-width',function () {
       return (this === HoveredLine) ? 4 : 2;
    })

;
})

This is achieved by giving the lines an id using classed. Using a different id, the lines in the other chart are selected similarly.

What I want to achieve is a way that if the line of e.g. group A is highlighted in one chart, it is also highlighted in the other chart also (and all other non-selected lines are faded in all charts). I thought maybe this could be done by getting the index of the selected line and somehow using that in the other chart.

1
Use classes, this is what they're for. You can select all of the lines with the given class and make your change.AJFarkas
@AJFarkas is it possible / how is it best to add classes to individual lines?jalapic

1 Answers

1
votes

We can solve it by having a single place where we handle mouseover and mouseout for both lines.

Primarily to avoid code repeat (DRY principle)

We will write mouse over and mouse out in a single place from where we can handle events in both svg.

So instead of attaching listeners individually like this

d3.selectAll('path.line.mainline')
    .on("mouseover", function(d) {

and

d3.selectAll('path.line.mainlinel')
    .on("mouseover", function(d) { 

Do it like this:

  d3.selectAll('path.line')//register this to all paths
    .on("mouseover", function(d,i) {

Make use of filter to get the lines on which it is hovered.

  d3.selectAll('path.line').filter(function(d1) {
      return d.name == d1.name; all which have same name get it via filter
    })
    .style("opacity", 1)//show filtered links
    .style("stroke-width", 4);

Full method will be like this:

function doHover() {
  d3.selectAll('path.line')//register this to all paths
    .on("mouseover", function(d,i) {
      //first make all lines vanish
      d3.selectAll('path.line')
        .style("opacity", 0.1)
        .style("stroke-width", 2)
      //only show lines which have same name.
      d3.selectAll('path.line').filter(function(d1) {
          return d.name == d1.name
        })
        .style("opacity", 1)
        .style("stroke-width", 4);

      d3.select("div#chartw.container svg")
        .append("text")
        .attr("id", "cohorttext")
        .html("Cohort " + d.name)
        .attr("x", (width) / 1.2)
        .attr("y", margin.top * 1.5)
        .style("fill", color(d.name))
        .style("font-weight", "bold")
        .style("font-size", "18px");

      d3.select("div#chartw.container svg")
        .append("text")
        .attr("id", "cohorttextx")
        .html("Gini = " + giniw[i%giniw.length])//so that its always within the max length
        .attr("x", (width) / 1.2)
        .attr("y", 20 + margin.top * 1.5)
        .style("fill", color(d.name))
        .style("font-size", "14px");  



    d3.select("div#chartl.container svg")
        .append("text")
        .attr("id", "cohorttext")
        .text("Cohort " + d.name)
        .attr("x", (width) / 1.2)
        .attr("y", margin.top * 1.5)
        .style("fill", color(d.name))
        .style("font-weight", "bold")
        .style("font-size", "18px");


   d3.select("div#chartl.container svg")
        .append("text")
        .attr("id", "cohorttextx")
        .html("Gini = " + ginil[i%ginil.length])//so that its always within the max length
        .attr("x", (width) / 1.2)
        .attr("y", 20 + margin.top * 1.5)
        .style("fill", color(d.name))
        .style("font-size", "14px");    
    })
    .on("mouseout", function() {
      d3.selectAll('path.line')
        .style("opacity", 1)
        .style("stroke-width", 2);
      //selectALL because we are giving same id to both text in 2 svgs  
      d3.selectAll("#cohorttext").remove()
      d3.selectAll("#cohorttextx").remove()  

    })
}

Working code here

Please let me know if you have any queries on this.