【问题标题】:D3 remove circle on dbclickD3 删除 dbclick 上的圆圈
【发布时间】:2018-03-05 05:19:54
【问题描述】:

我正在使用 Bostock 的 Circle Dragging I 和 Will 的 D3 Mouse Event,所以我可以点击 svg 并创建一个圆圈,而且它们都是可拖动的。这是可行的,尽管如果我在创建圆圈时双击有时会出现一个附带问题,拖动圆圈会导致它们跳来跳去。

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

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

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

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

此功能不会删除圆圈,这样做的正确方法是什么? 单击做一件事和双击做另一件事之间是否存在冲突?

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>

【问题讨论】:

    标签: javascript d3.js draggable geometry removeall


    【解决方案1】:

    您的代码将面临的最大问题是从双击中区分单击。但是,由于您专门询问了如何删除圆圈,因此此答案将仅处理该问题。

    您删除圆圈的代码有两个问题。

    首先,这个...

    .on("dblclick", removeElement())
    

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

    相反,这样做:

    .on("dblclick", removeElement) 
    

    与以下相同:

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

    这样,removeElement 只会在用户点击圆圈时被调用,而不是立即被调用。

    第二个问题是这样的:

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

    由于仍有与该圈子相关的数据,因此您的“退出”选择为空。

    应该是:

    d3.select(this).remove();
    

    这是您的代码进行了这些更改:

    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 的点击以创建圆圈。由于该问题(区分单击和双击)非常复杂,因此值得提出一个新的、单独的问题。

    【讨论】:

    • 我现在看到单击和双击是个坏主意。因此,我尝试单击画布以创建一个圆圈,然后单击一个圆圈以将其删除。我在这里问过这个问题stackoverflow.com/questions/46390307/… 谢谢
    猜你喜欢
    • 2012-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多