简体   繁体   English

D3 不正确的拖动行为

[英]D3 incorrect drag behaviour

This is a follow on from my previous question d3 rect in one group interfering with rect in another group这是我之前的问题d3 rect in one group in interfering with rect in another group的后续

Two issues:两个问题:

  1. Incorrect drag behaviour.不正确的拖动行为。 When clicking on the second rect to drag it, it jumps to where the third one is.单击第二个矩形拖动它时,它会跳到第三个矩形所在的位置。

  2. I added a anonymous function which runs when the svg in clicked on anywhere.我添加了一个匿名函数,当 svg 在任何地方点击时运行。 This should add a new rect.这应该添加一个新的矩形。 However that is the working.然而,这就是工作。

I know I should have only one issue per question but these are related and I suspect they will be solved together.我知道每个问题我应该只有一个问题,但这些是相关的,我怀疑它们会一起解决。

 <!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 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 dx; }) .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 dx }) .attr("y", 100) .attr("text-anchor", "start") .style("fill", "black") .text(function(d) { return "x:" + dx }); // 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 dx; }) .attr("y", 200) .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 dx }) .attr("y", 200) .attr("text-anchor", "start") .style("fill", "black") .text(function(d) { return "x:" + dx }); svg.on("click", function() { var coords = d3.mouse(this); var newData = { x: d3.event.x, } data.push(newData); group.selectAll("rect") .data(data) .enter() .append("rect") .attr("x", function(d) { return dx; }) .attr("y", 200) .attr("height", 100) .attr("width", 15) .style("fill", "steelblue") .attr('id', function(d, i) { return 'rect_' + i; }) .attr("rx", 6) .attr("ry", 6) .attr("stroke-width", 2) .attr("stroke", "black"); }); function dragstarted(d) { d3.select(this).raise().classed("active", true); } function dragged(d) { d3.select(this).select("text") .attr("x", dx = d3.event.x); d3.select(this).select("rect") .attr("x", dx = 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>

For correctly drag-and-drop behavior, rewrite your code like this:为了正确的拖放行为,像这样重写你的代码:

 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 dx; }) .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 dx }) .attr("y", 100) .attr("text-anchor", "start") .style("fill", "black") .text(function(d) { return "x:" + dx }); svg.on("click", function() { var coords = d3.mouse(this); var newData = { x: d3.event.x, } data.push(newData); group.selectAll("rect") .data(data) .exit() .enter() .append("rect") .attr("x", function(d) { return dx; }) .attr("y", 200) .attr("height", 100) .attr("width", 15) .style("fill", "steelblue") .attr('id', function(d, i) { return 'rect_' + i; }) .attr("rx", 6) .attr("ry", 6) .attr("stroke-width", 2) .attr("stroke", "black"); }); function dragstarted(d) { d3.select(this).raise().classed("active", true); } function dragged(d) { d3.select(this).select("text") .attr("x", dx = d3.event.x); d3.select(this).select("rect") .attr("x", dx = 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://cdnjs.cloudflare.com/ajax/libs/d3/4.10.2/d3.min.js"></script> <svg width="960" height="500"></svg>

But, what the problem with adding the new element, I have no idea.但是,添加新元素有什么问题,我不知道。

Here are the explanations to your issues:以下是对您的问题的解释:

  1. You are reassigning var groups , that is, you have two var groups in your code, the last one overwriting the first one.您正在重新分配var groups ,也就是说,您的代码中有两个var groups ,最后一个覆盖了第一个。 Just remove the last variable.只需删除最后一个变量。
  2. In your function to append new rectangles, you are using an update selection that selects rectangles.在追加新矩形的函数中,您使用的是选择矩形的更新选择。 However, your enter selection appends groups ( <g> ) elements, not rectangles.但是,您的输入选择会附加组 ( <g> ) 元素,而不是矩形。

Have a look at the refactored function, it binds the data to a newly created group and appends the rectangle to that group:看看重构的函数,它将数据绑定到一个新创建的组并将矩形附加到该组:

var newGroup = svg.selectAll(".group")
    .data(data, function(d) {
        return d.x
    })
    .enter()
    .append("g")
    //etc...

newGroup.append("rect")
    //etc...

Also, use a key selection in the data binding, so you know exactly what rectangle is being dragged:此外,在数据绑定中使用键选择,这样您就可以确切地知道正在拖动的矩形:

.data(data, function(d){return d.x})

Here is your code with those changes:这是带有这些更改的代码:

 <!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 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, function(d){return dx}) .enter().append("g") .attr("class", "group") .call(d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended)) .on("click", removeElement); group.append("rect") .attr("x", function(d) { return dx; }) .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 dx }) .attr("y", 100) .attr("text-anchor", "start") .style("fill", "black") .text(function(d) { return "x:" + dx }); svg.on("click", function() { var coords = d3.mouse(this); var newData = { x: coords[0], } data.push(newData); var newGroup = svg.selectAll(".group") .data(data, function(d){return dx}) .enter() .append("g") .attr("class", "group") .call(d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended)) .on("click", removeElement); newGroup.append("rect") .attr("x", function(d) { return dx; }) .attr("y", 200) .attr("height", 100) .attr("width", 15) .style("fill", "steelblue") .attr('id', function(d, i) { return 'rect_' + i; }) .attr("rx", 6) .attr("ry", 6) .attr("stroke-width", 2) .attr("stroke", "black"); }); function dragstarted(d) { d3.select(this).raise().classed("active", true); } function dragged(d) { d3.select(this).select("text") .attr("x", dx = d3.event.x); d3.select(this).select("rect") .attr("x", dx = 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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM