是否可以根据点击<g>选择<路径>?

时间:2018-01-16 06:50:04

标签: d3.js legend

我想做的是

  1. 我想点击图例(在rect和text上的任意位置)来显示/隐藏该段数据。我可以单独使用rect或单独使用文本,但不能同时使用(在'g'上)。所以,我想知道这是否可行。
  2. 点击后,我还要从该图例元素中检索文本/类别,因为我需要在colorScale()中重新指定原始颜色。
  3. 拿这个snippet,例如,我想点击'legend'类的'g',并获得附加到rect元素的文本。

    任何建议都将受到赞赏。

1 个答案:

答案 0 :(得分:1)

如果将数据绑定到<g>元素,则单击矩形和单击文本之间确实没有区别。在这两种情况下,您都可以检索数据。

但是,我们将使用名为clicked ...

的属性
legend.each(function(d) {
    d.clicked = false;
})

...为了处理点击,最好的想法是更改绑定到对象数组的数据:

var legend = svg.selectAll('.legend') // NEW
    .data(dataset)

相应地更改矩形和文本,以使用d.label

然后,在点击功能中,我们只做:

legend.on("click", function(d) {
    d.clicked = !d.clicked;
    console.log("Category is: " + d.label)
    path.filter(function(e) {
        return e.data.label === d.label
    }).style("opacity", d.clicked ? 0 : 1)
})

其中:

  1. 切换clicked属性;
  2. 根据标签过滤路径;
  3. 根据clicked属性设置样式。
  4. 这是带有更改的代码:

    &#13;
    &#13;
    var dataset = [{
      label: 'Abulia',
      count: 10
    }, {
      label: 'Betelgeuse',
      count: 20
    }, {
      label: 'Cantaloupe',
      count: 30
    }, {
      label: 'Dijkstra',
      count: 40
    }];
    
    var width = 360;
    var height = 360;
    var radius = Math.min(width, height) / 2;
    var donutWidth = 75;
    var legendRectSize = 18; // NEW
    var legendSpacing = 4; // NEW
    
    var color = d3.scaleOrdinal(d3.schemeCategory20b);
    
    var svg = d3.select('body')
      .append('svg')
      .attr('width', width)
      .attr('height', height)
      .append('g')
      .attr('transform', 'translate(' + (width / 2) +
        ',' + (height / 2) + ')');
    
    var arc = d3.arc()
      .innerRadius(radius - donutWidth)
      .outerRadius(radius);
    
    var pie = d3.pie()
      .value(function(d) {
        return d.count;
      })
      .sort(null);
    
    var path = svg.selectAll('path')
      .data(pie(dataset))
      .enter()
      .append('path')
      .attr('d', arc)
      .attr('fill', function(d, i) {
        return color(d.data.label);
      });
    
    var legend = svg.selectAll('.legend') // NEW
      .data(dataset) // NEW
      .enter() // NEW
      .append('g') // NEW
      .attr('class', 'legend')
      .style("cursor", "pointer")
      // NEW
      .attr('transform', function(d, i) { // NEW
        var height = legendRectSize + legendSpacing; // NEW
        var offset = height * color.domain().length / 2; // NEW
        var horz = -2 * legendRectSize; // NEW
        var vert = i * height - offset; // NEW
        return 'translate(' + horz + ',' + vert + ')'; // NEW
      }); // NEW
    
    legend.append('rect') // NEW
      .attr('width', legendRectSize) // NEW
      .attr('height', legendRectSize) // NEW
      .style('fill', function(d) {
        return color(d.label)
      }) // NEW
      .style('stroke', function(d) {
        return color(d.label)
      }); // NEW
    
    legend.append('text') // NEW
      .attr('x', legendRectSize + legendSpacing) // NEW
      .attr('y', legendRectSize - legendSpacing) // NEW
      .text(function(d) {
        return d.label;
      }); // NEW
    
    legend.each(function(d) {
      d.clicked = false;
    })
    
    legend.on("click", function(d) {
      d.clicked = !d.clicked;
      console.log("Category is: " + d.label)
      path.filter(function(e) {
        return e.data.label === d.label
      }).style("opacity", d.clicked ? 0 : 1)
    })
    &#13;
    .as-console-wrapper { max-height: 10% !important;}
    &#13;
    <script src="https://d3js.org/d3.v4.min.js"></script>
    &#13;
    &#13;
    &#13;