Jquery d3.js节点未正确退出

Jquery d3.js节点未正确退出,jquery,d3.js,dataset,Jquery,D3.js,Dataset,这就来了。我花了相当长的时间在这一点上-我真的很累-所以希望一些愚蠢的东西没有逃避我 我正在使用数据集在图表中创建几行。之后,使用图例,我想在更改数据集的同时隐藏线-因此更改不透明度不会剪切它 我遵循在数据集中的每个对象上添加一个启用键的路径,并将其设置为false,以便能够筛选要隐藏的对象。但是,由于我无法正确地退出()行,因此它没有按预期工作。完全删除行并再次绑定数据集可以完成任务,但会弄乱行颜色到图例项的映射 问题出在函数的某个地方 希望有人能解决这个噩梦 我创造了一把小提琴我理解你的感

这就来了。我花了相当长的时间在这一点上-我真的很累-所以希望一些愚蠢的东西没有逃避我

我正在使用数据集在图表中创建几行。之后,使用图例,我想在更改数据集的同时隐藏线-因此更改不透明度不会剪切它

我遵循在数据集中的每个对象上添加一个启用键的路径,并将其设置为false,以便能够筛选要隐藏的对象。但是,由于我无法正确地退出()行,因此它没有按预期工作。完全删除行并再次绑定数据集可以完成任务,但会弄乱行颜色到图例项的映射

问题出在函数的某个地方

希望有人能解决这个噩梦


我创造了一把小提琴

我理解你的感受。。。我希望这个答案能对你有所帮助

您的代码中有一些问题,因此我修复了主要问题,并在过程中添加了注释。 请记住,在我的版本中仍然有很多地方可以改进,这取决于您如何改进

我将用一些注释来更新答案,详细说明我对如何处理这段代码的想法,并在这里链接到一篇有用的文章或答案

同时检查此项和下面的代码

// .. code above is unchanged 
line = d3.line()
  .x(function(d) {
    return x(d.date);
  }).y(function(d) {
    return y(d.value);
  });

// notice I deleted the part where you created the groups and the path the first time 
// You don't need it anymore

var legendItem = d3.select(".legend")
  .selectAll("li")
  .data(dataGroup)
  .enter()
  .append("li")
  .on('click', function(d) {
    if (d.enabled) {
      d.enabled = false;
    } else {
      d.enabled = true;
    }
    redraw();
  });

legendItem
  .append("span")
  .attr("class","color-square")
  .style("background", function(d, i) {
    // This is basically a hack for this demo 
    // You should find a better way to assign an index to a color
    var idx = +d.key.slice(-1);  
    return colorScale(idx - 1);
  });

legendItem
  .append("span")
  .text(function(d) {
    return (d.values[0].name)
  });

redraw = function() {

  y.domain([
    d3.min(dataGroup, function(c) {
      return d3.min(c.values, function(d) {
        return d.value;
      });
    }),
    // In the demo I don't rescale after the datasets change, so no need to filter
    // by enabled sets. If you want the max to be calculated only for enabled items
    // you will also have to redraw the axis, otherwise you will display incorrect data.
    d3.max(dataGroup, function(c) { 
      return d3.max(c.values, function(d) {
        return d.value;
      });
    })
  ]);

  // Notice that i filter the data passed to the .data() function,
  // not after it.
  lines = svg.selectAll("g.d3-group")
    .data(dataGroup.filter(d => d.enabled))

  // This is the Enter + update selection
  var linesEnter = lines
    .enter()
    .append("g")
    .merge(lines)
    .attr("class", "d3-group")

  // We want the data to go from the <g> to its child, the <path> element
  // To do so, we need to rebind the data.
  var pathJoin = linesEnter
    .selectAll('path')
    .data(d => [d]) // <= this is very important

  // Enter the path and update it
  var pathEnter = pathJoin
    .enter()
    .append("path")
    .attr("class", "d3-line")
    .merge(pathJoin)    
    .attr('d', function(d) {
      return line(d.values);
    })
    // Notice how "i" is not used. If you log it you will see it is always 0
    // as it is always the first child of its parent, the <g class="group">
    .style("stroke", function(d, i) {
      var idx = +d.key.slice(-1);
      return colorScale(idx - 1);
    });


    lines.exit().remove(); 

}

redraw();
正确处理的一件重要事情是将数据从父级(
)传输到子级(
)。这里发生了这样的事情:

linesEnter
    .selectAll('path')
    .data(d => [d]) // <= here
linesEnter
.selectAll('路径')

.data(d=>[d])/我理解你的感受。。。我希望这个答案能对你有所帮助

您的代码中有一些问题,因此我修复了主要问题,并在过程中添加了注释。 请记住,在我的版本中仍然有很多地方可以改进,这取决于您如何改进

我将用一些注释来更新答案,详细说明我对如何处理这段代码的想法,并在这里链接到一篇有用的文章或答案

同时检查此项和下面的代码

// .. code above is unchanged 
line = d3.line()
  .x(function(d) {
    return x(d.date);
  }).y(function(d) {
    return y(d.value);
  });

// notice I deleted the part where you created the groups and the path the first time 
// You don't need it anymore

var legendItem = d3.select(".legend")
  .selectAll("li")
  .data(dataGroup)
  .enter()
  .append("li")
  .on('click', function(d) {
    if (d.enabled) {
      d.enabled = false;
    } else {
      d.enabled = true;
    }
    redraw();
  });

legendItem
  .append("span")
  .attr("class","color-square")
  .style("background", function(d, i) {
    // This is basically a hack for this demo 
    // You should find a better way to assign an index to a color
    var idx = +d.key.slice(-1);  
    return colorScale(idx - 1);
  });

legendItem
  .append("span")
  .text(function(d) {
    return (d.values[0].name)
  });

redraw = function() {

  y.domain([
    d3.min(dataGroup, function(c) {
      return d3.min(c.values, function(d) {
        return d.value;
      });
    }),
    // In the demo I don't rescale after the datasets change, so no need to filter
    // by enabled sets. If you want the max to be calculated only for enabled items
    // you will also have to redraw the axis, otherwise you will display incorrect data.
    d3.max(dataGroup, function(c) { 
      return d3.max(c.values, function(d) {
        return d.value;
      });
    })
  ]);

  // Notice that i filter the data passed to the .data() function,
  // not after it.
  lines = svg.selectAll("g.d3-group")
    .data(dataGroup.filter(d => d.enabled))

  // This is the Enter + update selection
  var linesEnter = lines
    .enter()
    .append("g")
    .merge(lines)
    .attr("class", "d3-group")

  // We want the data to go from the <g> to its child, the <path> element
  // To do so, we need to rebind the data.
  var pathJoin = linesEnter
    .selectAll('path')
    .data(d => [d]) // <= this is very important

  // Enter the path and update it
  var pathEnter = pathJoin
    .enter()
    .append("path")
    .attr("class", "d3-line")
    .merge(pathJoin)    
    .attr('d', function(d) {
      return line(d.values);
    })
    // Notice how "i" is not used. If you log it you will see it is always 0
    // as it is always the first child of its parent, the <g class="group">
    .style("stroke", function(d, i) {
      var idx = +d.key.slice(-1);
      return colorScale(idx - 1);
    });


    lines.exit().remove(); 

}

redraw();
正确处理的一件重要事情是将数据从父级(
)传输到子级(
)。这里发生了这样的事情:

linesEnter
    .selectAll('path')
    .data(d => [d]) // <= here
linesEnter
.selectAll('路径')

.data(d=>[d])/以下是使用以下修复程序重构的代码:

  • 将初始绘制和重绘浓缩为单个函数
  • 在这个单一功能中正确处理了输入、更新和退出模式
  • 用于修复数据绑定(保持数据的唯一性)
  • 对颜色使用
    d.key
    ,而不是索引(以修复漫游颜色)
  • 修复了一些常见的代码质量问题(缺少var关键字、根据选择而不是数据进行筛选等)
  • 我没有使用不透明度来“切换”线条,尽管这样也可以

    
    .折线图{
    宽度:800px;
    高度:200px;
    }
    .d3轴{
    字体系列:“Arial”,无衬线;
    字体大小:10px;
    }
    .d3线{
    填充:无;
    笔画宽度:2px;
    }
    .d3轴路径{
    填充:无;
    冲程:#e6;
    形状渲染:边缘清晰;
    不透明度:0;//删除轴
    }
    .d3轴线{
    填充:无;
    冲程:#eee;
    形状渲染:边缘清晰;
    }
    ulli{
    显示:内联块;
    左边距:10px;
    }
    .彩色广场{
    显示:块;
    浮动:左;
    右边距:3倍;
    宽度:20px;
    高度:20px;
    边框:1px实心#000;
    }
    
      风险值数据=[{ “名称”:“第1行”, “日期”:“2016-10-07T23:59:07Z”, “价值”:67 }, { “名称”:“第1行”, “日期”:“2016-10-15T11:35:32Z”, “价值”:57 }, { “名称”:“第1行”, “日期”:“2017-02-09T07:13:41Z”, “价值”:11 }, { “名称”:“第1行”, “日期”:“2016-11-16T21:18:03Z”, “价值”:12 }, { “名称”:“第1行”, “日期”:“2016-05-01T03:08:22Z”, “价值”:71 }, { “名称”:“第1行”, “日期”:“2016-10-01T08:15:08Z”, “价值”:64 }, { “名称”:“第1行”, “日期”:“2016-07-27T09:58:43Z”, “价值”:25 }, { “名称”:“第1行”, “日期”:“2016-04-15T12:20:35Z”, “价值”:15 }, { “名称”:“第1行”, “日期”:“2016-11-01T11:51:14Z”, “价值”:69 }, { “名称”:“第1行”, “日期”:“2016-10-05T23:27:50Z”, “价值”:12 }, { “名称”:“第1行”, “日期”:“2016-11-11T21:53:45Z”, “价值”:87 }, { “名称”:“第1行”, “日期”:“2017-01-22T17:22:10Z”, “价值”:10 }, { “名称”:“第1行”, “日期”:“2016-07-18T23:33:03Z”, “价值”:27 }, { “名称”:“第1行”, “日期”:“2017-01-04T14:35:53Z”, “价值”:6 }, { “名称”:“第1行”, “日期”:“2016-11-10T07:17:06Z”, “价值”:91 }, { “名称”:“第1行”, “日期”:“2016-04-18T00:40:18Z”, “价值”:56 }, { “名称”:“第1行”, “日期”:“2016-06-23T11:27:18Z”, “价值”:22 }, { “名称”:“第1行”, “日期”:“2016-08-10T12:53:00Z”, “价值”:18 }, { “名称”:“第1行”, “日期”:“2016-09-02T17:24:51Z”, “价值”:89 }, { “名称”:“第1行”, “日期”:“2016-06-08T03:09:20Z”, “价值”:27 }, { “名称”:“第1行”, “日期”:“2016-10-30T17:54:30Z”, “价值”:38 }, { “名称”:“第1行”, “日期”:“2017-01-22T01:56:44Z”, “价值”:99 }, { “名称”:“第1行”, “日期”:“2016-06-02T19:58:44Z”, “价值”:48 }, { “名称”:“第1行”, “日期”:“2016-07-12T01:04:56Z”, “价值”:68 }, { “名称”:“第1行”, “日期”:“2016-09-23T07:30:45Z”, “价值”:11 }, { “名称”:“第1行”, “日期”:“2016-11-08T05:18:12Z”, “价值”:29 }, { “名称”:“第1行”, “日期”:“2017-01-24T03:46:43Z”, “价值”:19 }, { “n