D3.js以rect单击删除数据



在很多帮助下,我可以单击矩形以删除它们。

但是我还能删除数据?当前存在一些奇怪的行为,例如先前已删除的矩形重新出现和矩形的创建与点击不同。我认为所有这些都是由于未删除数据而引起的。

我认为也许.exit()可能起作用,但事实并非如此。

这是一个工作片段。

<!DOCTYPE html>
<meta charset="utf-8">
<style>
  .active {
    stroke: #000;
    stroke-width: 2px;
  }
</style>
<svg width="960" height="500"></svg>
<script src="//d3js.org/d3.v4.min.js"></script>
<script>
  var svg = d3.select("svg"),
    width = +svg.attr("width"),
    height = +svg.attr("height"),
    radius = 32;
  var data = [{
      x: 100,
      y: 200
    },
    {
      x: 200,
      y: 300
    },
    {
      x: 300,
      y: 200
    },
    {
      x: 400,
      y: 300
    }
  ];
  var xScale = d3.scaleLinear()
    .domain([0, d3.max(data, function(d) {
      return d.x_pos
    })]).range([0, width]);
  svg.append("rect")
    .attr("x", 100)
    .attr("y", 250)
    .attr("rx", 2)
    .attr("ry", 2)
    .attr("height", 6)
    .attr("width", 800)
    .style("fill", "grey");
  svg.append("rect")
    .attr("x", 102)
    .attr("y", 252)
    .attr("rx", 2)
    .attr("ry", 2)
    .attr("height", 2)
    .attr("width", 796)
    .style("fill", "black");
  svg.selectAll("rect")
    .data(data)
    .enter().append("rect")
    .attr("x", function(d) {
      return d.x;
    })
    .attr("y", 200)
    .attr("height", 100)
    .attr("width", 15)
    .style("fill", "lightblue")
    .attr('id', function(d, i) {
      return 'rect_' + i;
    })
    .attr("rx", 6)
    .attr("ry", 6)
    .attr("stroke-width", 2)
    .attr("stroke", "black")
    .call(d3.drag()
      .on("start", dragstarted)
      .on("drag", dragged)
      .on("end", dragended))
    .on("click", removeElement);
  svg.on("click", function() {
    var coords = d3.mouse(this);
    var newData = {
      x: d3.event.x,
      y: d3.event.y
    };
    data.push(newData);
    svg.selectAll("rect")
      .data(data)
      .enter()
      .append("rect")
      .attr("x", function(d) {
        return d.x;
      })
      .attr("y", 200)
      .attr("height", 100)
      .attr("width", 15)
      .style("fill", "steelblue")
      .attr('id', function(d, i) {
        return 'circle_' + i;
      })
      .attr("rx", 6)
      .attr("ry", 6)
      .attr("stroke-width", 2)
      .attr("stroke", "black")
      .call(d3.drag()
        .on("start", dragstarted)
        .on("drag", dragged)
        .on("end", dragended))
      .on("click", removeElement);
  })
  function dragstarted(d) {
    d3.select(this).raise().classed("active", true);
  }
  function dragged(d) {
    d3.select(this)
      .attr("x", d.x = d3.event.x)
    // .attr("cy", d.y = d3.event.y);
  }
  function dragended(d) {
    d3.select(this)
      .classed("active", false);
  }
  function removeElement(d) {
    d3.event.stopPropagation();
    d3.select(this)
      .remove();
  }
</script>

这个问题是从这里开始的。

首先,您的数据数组有4个元素,但是您只附加了2个矩形。发生这种情况是因为您选择了该SVG中以前存在的矩形。因此,而不是:

svg.selectAll("rect")
    .data(data)
    .enter().append("rect")

应该是:

svg.selectAll(null)
    .data(data)
    .enter().append("rect")

回到您的问题:

d3具有根据数据来操纵元素的方法,但不能根据元素来操纵数据。

因此,您必须自己更改数据阵列。例如,removeElement内部:

function removeElement(d) {
    data = data.filter(function(e){
        return e != d;
    });
};

这是您的代码和这些更改:

<!DOCTYPE html>
<meta charset="utf-8">
<style>
  .active {
    stroke: #000;
    stroke-width: 2px;
  }
</style>
<svg width="960" height="500"></svg>
<script src="//d3js.org/d3.v4.min.js"></script>
<script>
  var svg = d3.select("svg"),
    width = +svg.attr("width"),
    height = +svg.attr("height"),
    radius = 32;
  var data = [{
      x: 100,
      y: 200
    },
    {
      x: 200,
      y: 300
    },
    {
      x: 300,
      y: 200
    },
    {
      x: 400,
      y: 300
    }
  ];
  var xScale = d3.scaleLinear()
    .domain([0, d3.max(data, function(d) {
      return d.x_pos
    })]).range([0, width]);
  svg.append("rect")
    .attr("x", 100)
    .attr("y", 250)
    .attr("rx", 2)
    .attr("ry", 2)
    .attr("height", 6)
    .attr("width", 800)
    .style("fill", "grey");
  svg.append("rect")
    .attr("x", 102)
    .attr("y", 252)
    .attr("rx", 2)
    .attr("ry", 2)
    .attr("height", 2)
    .attr("width", 796)
    .style("fill", "black");
  svg.selectAll(null)
    .data(data)
    .enter().append("rect")
    .attr("x", function(d) {
      return d.x;
    })
    .attr("y", 200)
    .attr("height", 100)
    .attr("width", 15)
    .style("fill", "lightblue")
    .attr('id', function(d, i) {
      return 'rect_' + i;
    })
    .attr("rx", 6)
    .attr("ry", 6)
    .attr("stroke-width", 2)
    .attr("stroke", "black")
    .call(d3.drag()
      .on("start", dragstarted)
      .on("drag", dragged)
      .on("end", dragended))
    .on("click", removeElement);
  svg.on("click", function() {
    var coords = d3.mouse(this);
    var newData = {
      x: d3.event.x,
      y: d3.event.y
    };
    data.push(newData);
    svg.selectAll("rect")
      .data(data)
      .enter()
      .append("rect")
      .attr("x", function(d) {
        return d.x;
      })
      .attr("y", 200)
      .attr("height", 100)
      .attr("width", 15)
      .style("fill", "steelblue")
      .attr('id', function(d, i) {
        return 'circle_' + i;
      })
      .attr("rx", 6)
      .attr("ry", 6)
      .attr("stroke-width", 2)
      .attr("stroke", "black")
      .call(d3.drag()
        .on("start", dragstarted)
        .on("drag", dragged)
        .on("end", dragended))
      .on("click", removeElement);
  })
  function dragstarted(d) {
    d3.select(this).raise().classed("active", true);
  }
  function dragged(d) {
    d3.select(this)
      .attr("x", d.x = d3.event.x)
    // .attr("cy", d.y = d3.event.y);
  }
  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>

最新更新