d3.js 节点未正确退出 [英] d3.js nodes are not exiting properly

查看:21
本文介绍了d3.js 节点未正确退出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

就这样吧.我在这个上花了相当长的时间——而且真的很累——所以希望我没有忘记一些愚蠢的事情.

so here goes. I've spent quite some time on this one - and am really tired - so hopefully something silly hasn't eluded me.

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

I am using a dataset to create a few lines in a chart. After that, using a legend I want to hide lines while also changing the dataset - so changing opacity won't cut it.

我遵循在我的数据集中的每个对象上添加一个启用密钥的路径并将其设置为 false,以便能够过滤要隐藏的对象.但是,它不能按预期工作,因为我无法正确 exit() 行.完全删除线条并再次绑定数据集可以完成工作,但会混淆线条颜色到图例项的映射.

I followed the path of adding a key enabled on each object in my dataset and set it to false in order to be able to filter objects to hide. However, It doesn't work as expected since I cannot exit() the lines properly. Removing the lines completely and binding the dataset again gets the job done but messes with the mapping of the line colors to the legend items.

问题出在 redraw() 函数的某个地方.

The problem lies somewhere in the redraw() function.

希望有人能够解决这个噩梦!

Hopefully someone is able to sort out this nightmare!

https://jsfiddle.net/2en21Lqh/2/

我已经创建了一个小提琴

I have created a fiddle

推荐答案

你的代码经过以下修复重构:

Here's your code refactored with the following fixes:

  1. 将初始绘制和重绘压缩为单个函数.
  2. 在这个单一函数中正确处理进入、更新、退出模式.
  3. 引入关键函数来修复数据绑定(保持数据唯一性).
  4. 使用 d.key 作为颜色而不是索引(以修复漂移的颜色).
  5. 修复了一些一般代码质量问题(缺少 var 关键字、过滤选择而不是数据等...)
  1. Condensed initial draw and redraw into single function.
  2. Properly handled enter, update, exit pattern in this single function.
  3. Introduced key function to fix data binding (keep it unique to the data).
  4. Use d.key for colors instead of index (to fix the wandering colors).
  5. Fixed some general code quality issues (missing var keywords, filtering on selection instead of data, etc...)

我没有使用不透明度切换"线条,尽管这样也可以.

I did not "toggle" the lines using opacity, although that would work as well.

<!DOCTYPE html>
<html>

<head>
  <script data-require="d3@4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
  <script data-require="jquery@3.0.0" data-semver="3.0.0" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js"></script>
  <style>
    .line-chart {
      width: 800px;
      height: 200px;
    }
    
    .d3-axis {
      font-family: 'Arial', sans-serif;
      font-size: 10px;
    }
    
    .d3-line {
      fill: none;
      stroke-width: 2px;
    }
    
    .d3-axis path {
      fill: none;
      stroke: #e6e6e6;
      shape-rendering: crispEdges;
      opacity: 0; // remove axes
    }
    
    .d3-axis line {
      fill: none;
      stroke: #eee;
      shape-rendering: crispEdges;
    }
    
    ul li {
      display: inline-block;
      margin-left: 10px;
    }
    
    .color-square {
      display: block;
      float: left;
      margin-right: 3px;
      width: 20px;
      height: 20px;
      border: 1px solid #000;
    }
  </style>
</head>

<body>
  <div class="line-chart"></div>
  <ul class="legend"></ul>
  <script>
    var data = [{
      "name": "line1",
      "date": "2016-10-07T23:59:07Z",
      "value": 67
    }, {
      "name": "line1",
      "date": "2016-10-15T11:35:32Z",
      "value": 57
    }, {
      "name": "line1",
      "date": "2017-02-09T07:13:41Z",
      "value": 11
    }, {
      "name": "line1",
      "date": "2016-11-16T21:18:03Z",
      "value": 12
    }, {
      "name": "line1",
      "date": "2016-05-01T03:08:22Z",
      "value": 71
    }, {
      "name": "line1",
      "date": "2016-10-01T08:15:08Z",
      "value": 64
    }, {
      "name": "line1",
      "date": "2016-07-27T09:58:43Z",
      "value": 25
    }, {
      "name": "line1",
      "date": "2016-04-15T12:20:35Z",
      "value": 15
    }, {
      "name": "line1",
      "date": "2016-11-01T11:51:14Z",
      "value": 69
    }, {
      "name": "line1",
      "date": "2016-10-05T23:27:50Z",
      "value": 12
    }, {
      "name": "line1",
      "date": "2016-11-11T21:53:45Z",
      "value": 87
    }, {
      "name": "line1",
      "date": "2017-01-22T17:22:10Z",
      "value": 10
    }, {
      "name": "line1",
      "date": "2016-07-18T23:33:03Z",
      "value": 27
    }, {
      "name": "line1",
      "date": "2017-01-04T14:35:53Z",
      "value": 6
    }, {
      "name": "line1",
      "date": "2016-11-10T07:17:06Z",
      "value": 91
    }, {
      "name": "line1",
      "date": "2016-04-18T00:40:18Z",
      "value": 56
    }, {
      "name": "line1",
      "date": "2016-06-23T11:27:18Z",
      "value": 22
    }, {
      "name": "line1",
      "date": "2016-08-10T12:53:00Z",
      "value": 18
    }, {
      "name": "line1",
      "date": "2016-09-02T17:24:51Z",
      "value": 89
    }, {
      "name": "line1",
      "date": "2016-06-08T03:09:20Z",
      "value": 27
    }, {
      "name": "line1",
      "date": "2016-10-30T17:54:30Z",
      "value": 38
    }, {
      "name": "line1",
      "date": "2017-01-22T01:56:44Z",
      "value": 99
    }, {
      "name": "line1",
      "date": "2016-06-02T19:58:44Z",
      "value": 48
    }, {
      "name": "line1",
      "date": "2016-07-12T01:04:56Z",
      "value": 68
    }, {
      "name": "line1",
      "date": "2016-09-23T07:30:45Z",
      "value": 11
    }, {
      "name": "line1",
      "date": "2016-11-08T05:18:12Z",
      "value": 29
    }, {
      "name": "line1",
      "date": "2017-01-24T03:46:43Z",
      "value": 19
    }, {
      "name": "line2",
      "date": "2016-04-17T06:36:39Z",
      "value": 44
    }, {
      "name": "line2",
      "date": "2016-03-27T17:40:29Z",
      "value": 29
    }, {
      "name": "line2",
      "date": "2016-09-13T02:11:44Z",
      "value": 55
    }, {
      "name": "line2",
      "date": "2016-12-24T10:47:49Z",
      "value": 54
    }, {
      "name": "line2",
      "date": "2016-11-12T21:17:27Z",
      "value": 74
    }, {
      "name": "line2",
      "date": "2016-07-17T10:18:03Z",
      "value": 55
    }, {
      "name": "line2",
      "date": "2016-10-15T10:46:42Z",
      "value": 24
    }, {
      "name": "line2",
      "date": "2016-08-25T12:10:23Z",
      "value": 63
    }, {
      "name": "line2",
      "date": "2017-01-22T18:08:27Z",
      "value": 88
    }, {
      "name": "line2",
      "date": "2016-05-04T09:47:14Z",
      "value": 44
    }, {
      "name": "line2",
      "date": "2016-10-19T18:45:20Z",
      "value": 74
    }, {
      "name": "line2",
      "date": "2017-01-16T19:03:01Z",
      "value": 46
    }, {
      "name": "line2",
      "date": "2017-01-03T18:05:28Z",
      "value": 32
    }, {
      "name": "line2",
      "date": "2016-09-22T14:32:07Z",
      "value": 93
    }, {
      "name": "line2",
      "date": "2016-08-26T16:07:09Z",
      "value": 22
    }, {
      "name": "line2",
      "date": "2016-08-12T07:03:45Z",
      "value": 52
    }, {
      "name": "line2",
      "date": "2016-10-09T11:12:56Z",
      "value": 52
    }, {
      "name": "line2",
      "date": "2016-10-11T00:13:01Z",
      "value": 39
    }, {
      "name": "line2",
      "date": "2016-10-23T16:35:20Z",
      "value": 58
    }, {
      "name": "line2",
      "date": "2016-07-06T05:18:24Z",
      "value": 95
    }, {
      "name": "line2",
      "date": "2017-02-03T08:49:39Z",
      "value": 51
    }, {
      "name": "line2",
      "date": "2016-07-21T00:03:27Z",
      "value": 100
    }, {
      "name": "line2",
      "date": "2016-08-27T07:23:05Z",
      "value": 71
    }, {
      "name": "line3",
      "date": "2016-11-11T21:53:45Z",
      "value": 87
    }, {
      "name": "line3",
      "date": "2017-01-22T17:22:10Z",
      "value": 220
    }, {
      "name": "line3",
      "date": "2016-07-18T23:33:03Z",
      "value": 24
    }, {
      "name": "line3",
      "date": "2017-01-04T14:35:53Z",
      "value": 65
    }, {
      "name": "line3",
      "date": "2016-11-10T07:17:06Z",
      "value": 9
    }, {
      "name": "line3",
      "date": "2016-04-18T00:40:18Z",
      "value": 54
    }, {
      "name": "line3",
      "date": "2016-06-23T11:27:18Z",
      "value": 72
    }, {
      "name": "line3",
      "date": "2016-08-10T12:53:00Z",
      "value": 88
    }, {
      "name": "line3",
      "date": "2016-09-02T17:24:51Z",
      "value": 89
    }, {
      "name": "line3",
      "date": "2016-06-08T03:09:20Z",
      "value": 27
    }, {
      "name": "line3",
      "date": "2016-10-30T17:54:30Z",
      "value": 38
    }, {
      "name": "line3",
      "date": "2017-01-22T01:56:44Z",
      "value": 99
    }, {
      "name": "line3",
      "date": "2016-06-02T19:58:44Z",
      "value": 48
    }, {
      "name": "line3",
      "date": "2016-07-12T01:04:56Z",
      "value": 68
    }, {
      "name": "line3",
      "date": "2016-09-23T07:30:45Z",
      "value": 51
    }, {
      "name": "line3",
      "date": "2016-11-08T05:18:12Z",
      "value": 49
    }, {
      "name": "line3",
      "date": "2017-01-24T03:46:43Z",
      "value": 89
    }, {
      "name": "line3",
      "date": "2016-04-17T06:36:39Z",
      "value": 54
    }, {
      "name": "line3",
      "date": "2016-03-27T17:40:29Z",
      "value": 27
    }, {
      "name": "line3",
      "date": "2016-09-13T02:11:44Z",
      "value": 58
    }, {
      "name": "line3",
      "date": "2016-12-24T10:47:49Z",
      "value": 24
    }, {
      "name": "line3",
      "date": "2016-11-12T21:17:27Z",
      "value": 54
    }, {
      "name": "line3",
      "date": "2016-07-17T10:18:03Z",
      "value": 55
    }, {
      "name": "line3",
      "date": "2016-10-15T10:46:42Z",
      "value": 24
    }, {
      "name": "line3",
      "date": "2016-08-25T12:10:23Z",
      "value": 63
    }]

    margin = {
      top: 20,
      right: 20,
      bottom: 20,
      left: 30
    };

    var containerwidth = $('.line-chart').width(),
        containerheight = $('.line-chart').height();


    var width = containerwidth - margin.left - margin.right,
       height = containerheight - margin.top - margin.bottom;

    var parseTime = d3.timeParse("%Y-%m-%dT%H:%M:%SZ")

    data.forEach(function(d) {
      d.date = parseTime(d.date);
      d.value = +d.value;
    });

    function sortByDateAscending(a, b) {
      return a.date - b.date;
    }
    dataset = data.sort(sortByDateAscending);

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

    dataGroup.forEach(function(d) {
      d.enabled = true;
    });
    
    var svg = d3.select('.line-chart')
      .append('svg')
      .attr('width', containerwidth)
      .attr('height', containerheight)
      .append('g')
      .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

    var x = d3.scaleTime().range([0, width]),
        y = d3.scaleLinear().range([height, 0]);

    var colorScale = d3.scaleOrdinal(d3.schemeCategory10);

    var xAxis = d3.axisBottom(x).ticks(20).tickSizeInner(2).tickSizeOuter(0);
    var yAxis = d3.axisLeft(y).ticks(5).tickSizeInner(-width).tickSizeOuter(0);
    var xAxisGroup = svg.append('g').attr('class', 'x d3-axis').attr('transform', 'translate(0,' + height + ')');
    var yAxisGroup = svg.append('g').attr('class', 'y d3-axis').attr('transform', 'translate(0,0)');

    var line = d3.line()
      .x(function(d) {
        return x(d.date);
      }).y(function(d) {
        return y(d.value);
      });

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

    legendItem
      .append("span")
      .attr("class", "color-square")
      .style("background", function(d, i) {
        return colorScale(d.key);
      });

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

    redraw();

    function redraw() {

      var fData = dataGroup.filter(function(d) {
        return d.enabled;
      });
      
      y.domain([
        d3.min(fData, function(c) {
          return d3.min(c.values, function(d) {
            return d.value;
          });
        }),
        d3.max(fData, function(c) {
          return d3.max(c.values, function(d) {
            return d.value;
          });
        })
      ]);
      
      x.domain([
        d3.min(fData, function(c) {
          return d3.min(c.values, function(d) {
            return d.date;
          });
        }),
        d3.max(fData, function(c) {
          return d3.max(c.values, function(d) {
            return d.date;
          });
        })
      ]);
      
      xAxisGroup.call(xAxis);
      yAxisGroup.call(yAxis);

      // update selection
      lines = svg.selectAll(".d3-group")
        .data(fData, function(d) {
          return d.key
        });

      // exit the whole group
      lines
        .exit().remove();

      // enter selection
      linesEnter = lines
        .enter()
        .append("g")
        .attr("class", "d3-group");
        
      // add path on enter
      linesEnter.append("path")
        .attr("class", "d3-line");
        
      // add text on enter
      linesEnter.append("text")
        .attr("class", "my-label")
        .attr("x", function(d,i){
          return i * 100;
        })
        .attr("y", 10);
        
      // update + enter
      lines = lines.merge(linesEnter);
      
      // adjust label
      lines.select(".my-label")
        .text(function(d,i){
          return "hi Mom " + d.key;
        });

      // adjust path
      lines.select(".d3-line")
        .attr('d', function(d) {
          return line(d.values);
        })
        .style("stroke", function(d, i) {
          return colorScale(d.key);
        });

    }
  </script>
</body>

</html>

这篇关于d3.js 节点未正确退出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆