首页 > 解决方案 > 如何协调多个数据可视化之间的交互,特别是当其中一个使用嵌套时?JavaScript 和 D3

问题描述

对于一个项目,我试图根据汽车统计数据对数据进行三种可视化,如果你将鼠标悬停在一个上,其他的也会显示悬停的影响。第一个是条形图,第二个是散点图,第三个是折线图。对于折线图,我想按制造商分组,这样我的折线图上就没有几百条线了,因为 x 和 y 上的绘图坐标是加速度和车型年份。另外两个不需要以这种方式分组,因为它们的轴之一是制造商。

我有从折线图到其他两个工作的交互,因为条形图或散点图上没有嵌套,并且散点图和条形图都可以很好地相互影响,但是由于数据是为折线图嵌套的,我似乎无法弄清楚如何访问它,因为我为其他两个(使用过滤)做的方式似乎不起作用。

下面我首先展示当鼠标悬停时我试图在哪里创建交互(这是用于条形图),在下面我包括如何设置我的折线图以显示它是如何工作的。我想要的只是当我将鼠标悬停在条形图或图上(在散点图中)时,通过加粗笔划来使相应的线条从其他线条中更加突出,然后在移动光标时恢复正常大小。我按照 D3 网站上关于折线图的教程进行操作,因此该代码应该没有什么特别错误的地方。

为条形图创建条形,mouseover 和 mouseout 是重要的部分:

var path1 = svg1.selectAll("myRect")
    .data(data)
    .enter()
    .append("rect")
    .attr("x", x1(0.1) )
    .attr("y", function(d) { return y1(d.Manufacturer); })
    .attr("height", y1.bandwidth() )
    .attr("width", function(d) { return x1(d.Cylinders); })
    .attr("fill", function (d) {
      return color1(d.Cylinders);
    })
    .on('mouseover', function (d, i) {
      svg1.selectAll('rect')
            .filter(function(f) {
                return f.Manufacturer === d.Manufacturer;
            })
            .attr("fill", function (d) {
              return color4(d.Cylinders);
            })
      svg2.selectAll('circle')
          .filter(function(f) {
            return f.Manufacturer === d.Manufacturer;
          })
          .attr('r', 9)
          .attr("fill", function (d) {
            return color5(d.Horsepower);
          });
      svg3.selectAll('path') //THIS IS THE LINE GRAPH
        .filter(function(f) {
           console.log(this)
          return ;           // <-------This is where I don't know what to return to just get one line
        })
        .attr("stroke-width", 7)
})
 .on('mouseout', function (d, i) {
      svg1.selectAll('rect')
          .filter(function(f) {
            return f.Manufacturer === d.Manufacturer;
          })
          .attr("fill", function (d) {
            return color1(d.Cylinders);
          });
      svg2.selectAll('circle')
           .filter(function(f) {
            return f.Manufacturer === d.Manufacturer;
           })
           .attr('r', 5)
           .attr("fill", function (d) {
            return color2(d.Acceleration);
          });
      d3.selectAll('path')           //DELESLECTING LINE GRAPH
           .filter(function(f) {
            return f.key === d.Manufacturer; //this is what I tried before but it doesn't work
           })
           .attr("stroke-width", 1.5)
 }); 

创建折线图:

var sumstat = d3.nest()
.key(function(d) { return d.Manufacturer;})
.entries(data);

// Add X axis 
var x3 = d3.scaleLinear()
.domain([69, 84])
.range([ 0, width3 ]);

svg3.append("g")
.attr("transform", "translate(0," + height3 + ")")
.call(d3.axisBottom(x3).ticks(5));

// Add Y axis
var y3 = d3.scaleLinear()
.domain([8, d3.max(data, function(d) { return +d.Acceleration; })])
.range([ height3, 0 ]);
svg3.append("g")
.call(d3.axisLeft(y3));

var div3 = d3.select("#my_div").append("div")
     .attr("class", "#tool_tip")
     .style("opacity", 0)
     .style("font-size", "xx-large");

// color palette
var res = sumstat.map(function(d){ return d.key }) // list of group names
var color = d3.scaleOrdinal()
.domain(res)
.range(['darkolivegreen','darkred','palevioletred','indianred', 'hotpink']) 

// Draw the line
svg3.selectAll(".line")
  .data(sumstat)
  .enter()
  .append("path")
    .attr("fill", "none")
    .attr("stroke", function(d){ return color(d.key) })
    .attr("stroke-width", 1.5)
    .attr("d", function(d){
      return d3.line()
        .x(function(d) { return x3(d.ModelYear); })
        .y(function(d) { return y3(+d.Acceleration); })
        (d.values)
    })
    .on('mouseover', function (d, i) {
      //highlight;
      svg3.selectAll("path")
        .attr("stroke-width", 0.9)
      d3.select(this)
          .attr("stroke", function(d){ return color(d.key)})
          .attr("stroke-width", 6)
      svg1.selectAll('rect')
            .filter(function(f) { 
              return f.Manufacturer === d.key;
            })
            .attr("fill", function (d) {
              return color4(d.Cylinders);
            })
      svg2.selectAll('circle')
            .filter(function(f) {
                return f.Manufacturer === d.key;
            })
            .attr('r', 9)
            .attr("fill", function (d) {
              return color5(d.Horsepower);
            });
  })
 .on('mouseout', function (d, i) {
      svg3.selectAll("path")
          .attr("stroke-width", 1.5)
      d3.select(this)
          .attr("stroke", function(d){ return color(d.key)})
          .attr("stroke-width", 1.5)
      svg1.selectAll('rect')
          .filter(function(f) {
            return f.Manufacturer === d.key;
           })
          .attr("fill", function (d) {
             return color1(d.Cylinders);
           })
      svg2.selectAll('circle')
          .filter(function(f) {
            return f.Manufacturer === d.key;
           })
           .attr('r', 5)
           .attr("fill", function (d) {
            return color2(d.Horsepower);
          });
  });

我能得到的任何帮助将不胜感激!!

标签: javascriptd3.jsnesteddata-visualizationinteractive

解决方案


我想我可能已经找到了问题所在。似乎尝试过滤路径会导致问题,因为 x 和 y 轴在技术上也是线,因此路径为空。我试过了

svg3.selectAll('path')
          .filter(function(f) {
             console.log(f)
             if(f!=null)
                return f.key === d.Manufacturer;
          })
            .attr("stroke-width",7)

在 .on('mouseover') 函数中,它似乎正在工作。问题是空值,而不是键的实际访问。

如果有更好的方法来做到这一点,仍然会接受建议!


推荐阅读