d3单击创建圆,然后单击删除 [英] d3 Click to create circle and click to remove

查看:96
本文介绍了d3单击创建圆,然后单击删除的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图单击一个圆圈将其删除,但是在画布上单击将创建一个圆圈.

我确实想从数据中删除圆及其对象,而不是仅使其透明.

在圆圈上单击会调用该功能

  function removeElement(d) {
    d3.select(this)
      .remove();
  }

只需在圆上单击一下即可调用此功能,

  .on("click", removeElement);

我认为我没有正确区分单击画布以创建一个不存在的圆圈和单击现有圆圈以将其删除.

 <!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.selectAll("circle")
    .data(data)
    .enter().append("circle")
    .attr("cx", function(d) {
      return d.x;
    })
    .attr("cy", function(d) {
      return d.y;
    })
    .attr("r", radius)
    .style("fill", "lightblue")
    .attr('id', function(d, i) {
      return 'rect_' + i;
    })
    .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("circle") // For new circle, go through the update process
      .data(data)
      .enter()
      .append("circle")
      .attr("cx", function(d) {
        return d.x;
      })
      .attr("cy", function(d) {
        return d.y;
      })
      .attr("r", radius)
      .style("fill", "red")
      .attr('id', function(d, i) {
        return 'circle_' + i;
      })
      .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("cx", d.x = d3.event.x)
      .attr("cy", d.y = d3.event.y);
  }

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

  function removeElement(d) {
    // need to remove this object from data
    d3.select(this)
      .remove();
  }
</script> 

此问题是对 D3删除dbclick上的圆圈

谢谢

解决方案

现在,您的代码存在的问题是,如果单击一个蓝色圆圈,它将删除该圆圈并创建一个新的红色圆圈.发生这种情况是因为事件冒泡到SVG父元素.

一个简单的解决方案是在removeElement函数内部进行此操作:

d3.event.stopPropagation();

文档所述, ...

...防止当前事件在捕获和冒泡阶段进一步传播.

以下是具有此更改的代码:

 <!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.selectAll("circle")
    .data(data)
    .enter().append("circle")
    .attr("cx", function(d) {
      return d.x;
    })
    .attr("cy", function(d) {
      return d.y;
    })
    .attr("r", radius)
    .style("fill", "lightblue")
    .attr('id', function(d, i) {
      return 'rect_' + i;
    })
    .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("circle") // For new circle, go through the update process
      .data(data)
      .enter()
      .append("circle")
      .attr("cx", function(d) {
        return d.x;
      })
      .attr("cy", function(d) {
        return d.y;
      })
      .attr("r", radius)
      .style("fill", "red")
      .attr('id', function(d, i) {
        return 'circle_' + i;
      })
      .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("cx", 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();
    // need to remove this object from data
    d3.select(this)
      .remove();
  }
</script> 

PS:您可能现在已经知道,我不太愿意回答同一问题中的不同问题(这是我始终建议OP避免的事情).因此,我不处理数据问题,即删除与clicked元素关联的数据.您总是可以问一个另一个问题...这是免费的!

I am trying to click on a circle to remove it, but clicking on the canvas will create a circle.

I do want to actually remove the circle and it's object from the data, as opposed to just making it transparent.

On click on a circle calls the function

  function removeElement(d) {
    d3.select(this)
      .remove();
  }

This function is called with a basic click on the circle,

  .on("click", removeElement);

I think I'm not correctly distinguishing between clicking on the canvas to create a circle where none exists and clicking on an existing circle to remove it.

<!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.selectAll("circle")
    .data(data)
    .enter().append("circle")
    .attr("cx", function(d) {
      return d.x;
    })
    .attr("cy", function(d) {
      return d.y;
    })
    .attr("r", radius)
    .style("fill", "lightblue")
    .attr('id', function(d, i) {
      return 'rect_' + i;
    })
    .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("circle") // For new circle, go through the update process
      .data(data)
      .enter()
      .append("circle")
      .attr("cx", function(d) {
        return d.x;
      })
      .attr("cy", function(d) {
        return d.y;
      })
      .attr("r", radius)
      .style("fill", "red")
      .attr('id', function(d, i) {
        return 'circle_' + i;
      })
      .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("cx", d.x = d3.event.x)
      .attr("cy", d.y = d3.event.y);
  }

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

  function removeElement(d) {
    // need to remove this object from data
    d3.select(this)
      .remove();
  }
</script>

This question is an extension of the question D3 remove circle on dbclick

Thanks,

解决方案

The problem with your code right now is that, if you click on a blue circle, it will both delete that circle and create a new, red circle. That happens because the event bubbles up to the SVG parent element.

An easy solution is doing this inside the removeElement function:

d3.event.stopPropagation();

As the documentation explains, stopPropagation...

... prevents further propagation of the current event in the capturing and bubbling phases.

Here is the code with that change:

<!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.selectAll("circle")
    .data(data)
    .enter().append("circle")
    .attr("cx", function(d) {
      return d.x;
    })
    .attr("cy", function(d) {
      return d.y;
    })
    .attr("r", radius)
    .style("fill", "lightblue")
    .attr('id', function(d, i) {
      return 'rect_' + i;
    })
    .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("circle") // For new circle, go through the update process
      .data(data)
      .enter()
      .append("circle")
      .attr("cx", function(d) {
        return d.x;
      })
      .attr("cy", function(d) {
        return d.y;
      })
      .attr("r", radius)
      .style("fill", "red")
      .attr('id', function(d, i) {
        return 'circle_' + i;
      })
      .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("cx", 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();
    // need to remove this object from data
    d3.select(this)
      .remove();
  }
</script>

PS: As you probably know by now, I'm not a big fan of answering different problems in the same question (which is something that I always advise OPs to avoid). Therefore, I'm not dealing with the data issue, that is, removing the data associated with the clicked element. You can always ask another question... it's free!

这篇关于d3单击创建圆,然后单击删除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆