D3删除dbclick上的圆圈 [英] D3 remove circle on dbclick

查看:116
本文介绍了D3删除dbclick上的圆圈的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Bostock的圆拖动I 和Will的

I am using Bostock's Circle Dragging I and Will's D3 Mouse Event so i can click on svg and create a circle and also they are all draggable. That is working, although there is a side issue if I double click when creating a circle sometimes dragging circles causes them to jump around.

但是主要问题是我希望能够双击一个圆并使其消失,但也可以将其从数据中删除.

But the main issue is that I would like to be able to double click on a circle and have it disappear but also remove it from the data.

绘制圆圈时,我添加了一个dbclick事件,该事件调用了一个函数

When circles are drawn I added a dbclick event which calls a function

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

创建新圈子时也会调用此函数.

This function is also called when a new circle is created.

此功能未删除圈子,这样做的正确方法是什么? 一次点击做某件事与双击一次做其他事情之间有冲突吗?

This function is not removing circles, what is the correct way to do this? And is there a conflict between a single click doing one thing and a double click doing something else?

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("dblclick", 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("dblclick", 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)
    .exit()
    .remove();
}

.active {
  stroke: #000;
  stroke-width: 2px;
}

<!DOCTYPE html>
<meta charset="utf-8">
<svg width="960" height="500"></svg>
<script src="//d3js.org/d3.v4.min.js"></script>

推荐答案

您的代码所面临的最大问题是如何双击.但是,由于您专门询问了如何删除圆圈,因此此答案只能解决该问题.

The biggest issue you'll face with your code is telling a click from a double click. However, since you asked specifically how to remove the circles, this answer will deal with that problem only.

您用于删除圆圈的代码有两个问题.

Your code for removing the circles has two problems.

首先,这个...

.on("dblclick", removeElement())

...将立即调用removeElement并返回其值(顺便说一下,它是undefined).这不是您想要的.

... will call removeElement immediately and return its value (which, by the way, is undefined). This is not what you want.

相反,请执行以下操作:

Instead, do this:

.on("dblclick", removeElement) 

与以下相同:

.on("dbclick", function(d){
    removeElement(d);
}

这样,仅当用户单击圆圈时,才会立即调用removeElement.

That way, removeElement will be called only when the user clicks the circle, not immediately.

第二个问题是:

d3.select(this).exit().remove();

由于仍然有与该圆相关的数据,因此您的退出"选择为空.

Since there are still data associated with that circle, your "exit" selection is empty.

相反,它应该是:

d3.select(this).remove();

这是您所做的更改的代码:

Here is your code with those changes:

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("dblclick", 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();
}

.active {
  stroke: #000;
  stroke-width: 2px;
}

<!DOCTYPE html>
<meta charset="utf-8">
<svg width="960" height="500"></svg>
<script src="//d3js.org/d3.v4.min.js"></script>

PS:我删除了用于创建圆圈的SVG上的单击.由于该问题(区分点击与双击)非常复杂,因此可能值得提出一个单独的新问题.

PS: I removed the click on the SVG for creating the circles. Since that issue (distinguishing click from double click) is very complex, it may be worth a new, separated question.

这篇关于D3删除dbclick上的圆圈的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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