d3 rect in one group interfering with rect in anot

2019-08-08 13:28发布

问题:

I have a group called groove which has two rects. These are not bound to the data.

I also have a group called group which has many rects which are bound to the data.

In the second group called group there are only three data points, but only two are displaying.

Why is the first one not being rendered?

I have seen this before but can't remember how to solve it.

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>

回答1:

When you do this:

var group = svg.selectAll("g")

You are selecting a previously existing group (which is groove). Therefore, your enter selection has one less element.

Solution

Select nothing:

var group = svg.selectAll(null)

Here is your code with that change:

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>



标签: d3.js rect