一组中的 d3 rect 干扰另一组中的 rect

d3 rect in one group interfering with rect in another group

我有一个名为 groove 的组,它有两个矩形。这些未绑定到数据。

我还有一个名为 group 的组,其中有许多绑定到数据的矩形。

在名为 group 的第二组中,只有三个数据点,但只有两个正在显示。

为什么第一个没有被渲染?

我以前见过这个,但不记得如何解决了。

var margin = {
      top: 20,
      right: 20,
      bottom: 20,
      left: 20
    },
    width = 600 - margin.left - margin.right,
    height = 600 - margin.top - margin.bottom;

  var svg = d3.select("svg");

  var data = [{
      x: 200
    },
    {
      x: 300
    },
    {
      x: 400
    }
  ];

  var groove = svg.append("g")
    .attr("class", "groove_group");

  groove.append("rect")
    .attr("x", 100)
    .attr("y", 150)
    .attr("rx", 2)
    .attr("ry", 2)
    .attr("height", 6)
    .attr("width", 800)
    .style("fill", "grey");

  groove.append("rect")
    .attr("x", 102)
    .attr("y", 152)
    .attr("rx", 2)
    .attr("ry", 2)
    .attr("height", 2)
    .attr("width", 796)
    .style("fill", "black");

  // create group
  var group = svg.selectAll("g")
    .data(data)
    .enter().append("g")
    .call(d3.drag()
      .on("start", dragstarted)
      .on("drag", dragged)
      .on("end", dragended))
    .on("click", removeElement);

  group.append("rect")
    .attr("x", function(d) {
      return d.x;
    })
    .attr("y", 100)
    .attr("height", 100)
    .attr("width", 15)
    .style("fill", "lightblue")
    .attr('id', function(d, i) {
      return 'handle_' + i;
    })
    .attr("rx", 6)
    .attr("ry", 6)
    .attr("stroke-width", 2)
    .attr("stroke", "black");

  group.append("text")
    .attr("x", function(d) {
      return d.x
    })
    .attr("y", 100)
    .attr("text-anchor", "start")
    .style("fill", "black")
    .text(function(d) {
      return "x:" + d.x
    });

  function dragstarted(d) {
    d3.select(this).raise().classed("active", true);
  }

  function dragged(d) {
    d3.select(this).select("text")
      .attr("x", d.x = d3.event.x);
    d3.select(this).select("rect")
      .attr("x", d.x = d3.event.x);
  }

  function dragended(d) {
    d3.select(this)
      .classed("active", false);
  }

  function removeElement(d) {
    d3.event.stopPropagation();
    data = data.filter(function(e) {
      return e != d;
    });
    d3.select(this)
      .remove();
  }
<svg width="960" height="500"></svg>
<script src="//d3js.org/d3.v4.min.js"></script>

当你这样做时:

var group = svg.selectAll("g")

您正在选择一个以前存在的组(groove)。因此,您的输入选择少了一个元素。

解决方案

Select 没有:

var group = svg.selectAll(null)

这是您的代码,其中包含该更改:

var margin = {
    top: 20,
    right: 20,
    bottom: 20,
    left: 20
  },
  width = 600 - margin.left - margin.right,
  height = 600 - margin.top - margin.bottom;

var svg = d3.select("svg");

var data = [{
  x: 200
}, {
  x: 300
}, {
  x: 400
}];

var groove = svg.append("g")
  .attr("class", "groove_group");

groove.append("rect")
  .attr("x", 100)
  .attr("y", 150)
  .attr("rx", 2)
  .attr("ry", 2)
  .attr("height", 6)
  .attr("width", 800)
  .style("fill", "grey");

groove.append("rect")
  .attr("x", 102)
  .attr("y", 152)
  .attr("rx", 2)
  .attr("ry", 2)
  .attr("height", 2)
  .attr("width", 796)
  .style("fill", "black");

// create group
var group = svg.selectAll(null)
  .data(data)
  .enter().append("g")
  .call(d3.drag()
    .on("start", dragstarted)
    .on("drag", dragged)
    .on("end", dragended))
  .on("click", removeElement);

group.append("rect")
  .attr("x", function(d) {
    return d.x;
  })
  .attr("y", 100)
  .attr("height", 100)
  .attr("width", 15)
  .style("fill", "lightblue")
  .attr('id', function(d, i) {
    return 'handle_' + i;
  })
  .attr("rx", 6)
  .attr("ry", 6)
  .attr("stroke-width", 2)
  .attr("stroke", "black");

group.append("text")
  .attr("x", function(d) {
    return d.x
  })
  .attr("y", 100)
  .attr("text-anchor", "start")
  .style("fill", "black")
  .text(function(d) {
    return "x:" + d.x
  });

function dragstarted(d) {
  d3.select(this).raise().classed("active", true);
}

function dragged(d) {
  d3.select(this).select("text")
    .attr("x", d.x = d3.event.x);
  d3.select(this).select("rect")
    .attr("x", d.x = d3.event.x);
}

function dragended(d) {
  d3.select(this)
    .classed("active", false);
}

function removeElement(d) {
  d3.event.stopPropagation();
  data = data.filter(function(e) {
    return e != d;
  });
  d3.select(this)
    .remove();
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="960" height="500"></svg>