【问题标题】:Is it possible to select a <path> based on a click on <g>?是否可以通过单击 <g> 来选择 <path>?
【发布时间】:2018-06-24 19:42:05
【问题描述】:

我想做的是

  1. 我想单击图例(矩形和文本上的任意位置)以显示/隐藏该数据段。我可以单独在 rect 上或单独在 text 上执行此操作,但不能在两者上(在“g”上)。所以,我想知道这是否可行。
  2. 单击后,我还想从该图例元素中检索文本/类别,因为我需要重新分配 colorScale() 中的原始颜色。

snippet为例,我想点击“legend”类的“g”,同时获取附加到rect元素的文本。

任何建议将不胜感激。

【问题讨论】:

    标签: d3.js legend


    【解决方案1】:

    如果将数据绑定到&lt;g&gt;元素上,点击矩形和点击文本其实没有区别。在这两种情况下,您都可以检索数据。

    但是,因为我们将使用一个名为 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 属性设置它们的样式。

    这是更改后的代码:

    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)
    })
    .as-console-wrapper { max-height: 10% !important;}
    &lt;script src="https://d3js.org/d3.v4.min.js"&gt;&lt;/script&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-15
      • 2020-07-04
      • 2014-10-16
      • 1970-01-01
      • 2012-02-13
      • 1970-01-01
      • 2013-12-31
      • 2015-04-12
      相关资源
      最近更新 更多