[英]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:两个问题:
Incorrect drag behaviour.不正确的拖动行为。 When clicking on the second rect to drag it, it jumps to where the third one is.单击第二个矩形拖动它时,它会跳到第三个矩形所在的位置。
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:以下是对您的问题的解释:
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.只需删除最后一个变量。<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.