简体   繁体   中英

Link lines across small multiple charts d3js

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 eg 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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM