【发布时间】:2019-11-06 10:31:04
【问题描述】:
我有一个包含一些组和拖动行为的 SVG。它工作得很好,但是当我两次拖动元素时,它们会从“初始”位置重新开始。我需要新鲜的眼光来解决这个问题!
示例:jsfiddle
还有一个sn-p:
var items = [{name:"A", x:50, y:50}, {name:"B", x:150, y:50}];
var size = 96;
var svg = d3.select("#container")
.append("svg");
var items = svg.selectAll("g")
.data(items)
.enter()
.append("g")
.attr("transform", function(d, i){
return "translate(" + (10+i*size+10*i) + "," + 10 + ")";
});
items.call(d3.drag()
// .subject(function(d) { return d; })
// .on("start", dragstarted)
.on("drag", draggedGroup)
.subject(function() {
var t = d3.select(this);
return {x: t.attr("x"), y: t.attr("y")};
})
//.on("end", dragended)
);
items
.append("rect")
.attr("x",function(d){return d.x;})
.attr("y",function(d){return d.y;})
.attr("height",size)
.attr("width", size)
.style("stroke", "#0F0")
.style("fill", "transparent")
.style("stroke-width", 3.5);
items.append("line")
.style("stroke", "#0FF")
.attr("x1", function(d){return d.x;})
.attr("y1", function(d){return d.y;})
.attr("x2", function(d){return d.x+size;})
.attr("y2", function(d){return d.y+size;})
items.append("line")
.style("stroke", "#0FF")
.attr("x1", function(d){return d.x+size;})
.attr("y1", function(d){return d.y;})
.attr("x2", function(d){return d.x;})
.attr("y2", function(d){return d.y+size;})
items .append("text")
.attr("x", function(d){return d.x+size/2})
.attr("y", function(d){return d.y+size/2})
//.attr("text-anchor", "start")
.style("fill", "white")
.text(function(d){
return d.name;
})
function dragstarted(d){
console.log("Moving "+d.name);
// d3.select(this).raise().classed("active", true);
}
function draggedGroup(d, i, a){
const pos = [d3.event.x , d3.event.y];
const pdist = [d3.event.dx , d3.event.dy];
d3.select(this).attr("transform", "translate("+pos[0]+","+pos[1]+")")
}
function dragended(d){
// d3.select(this).raise().classed("active", false);
console.log("Stop moving "+d.name)
}
body{
background-color:black;
padding:10px;
}
svg{
width:500px;
height:400px;
}
#container{
width:500px;
height:400px;
background-color: #00F;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="container"></div>
我的分组项:
var items = svg.selectAll("g")
.data(items)
.enter()
.append("g")
.attr("transform", function(d, i){
return "translate(" + d.x + "," + d.y + ")";
});
items.append("rect")
.attr("x",function(d){return d.x;})
.attr("y",function(d){return d.y;})
.attr("height",size)
.attr("width", size)
.style("stroke", "#0F0")
.style("fill", "transparent")
.style("stroke-width", 3.5);
items.append("line")
.style("stroke", "#0FF")
.attr("x1", function(d){return d.x;})
.attr("y1", function(d){return d.y;})
.attr("x2", function(d){return d.x+size;})
.attr("y2", function(d){return d.y+size;})
items.append("line")
.style("stroke", "#0FF")
.attr("x1", function(d){return d.x+size;})
.attr("y1", function(d){return d.y;})
.attr("x2", function(d){return d.x;})
.attr("y2", function(d){return d.y+size;})
items .append("text")
.attr("x", function(d){return d.x+size/2})
.attr("y", function(d){return d.y+size/2})
//.attr("text-anchor", "start")
.style("fill", "white")
.text(function(d){
return d.name;
})
行为
items.call(d3.drag()
.on("drag", draggedGroup)
.subject(function() {
var t = d3.select(this);
return {x: t.attr("x"), y: t.attr("y")};
})
);
拖动功能
function draggedGroup(d, i, a){
const pos = [d3.event.x , d3.event.y];
d3.select(this).attr("transform", "translate("+pos[0]+","+pos[1]+")")
}
为什么当我第二次尝试拖动元素时它从第一个位置重新开始?请参阅 jsfiddle 上的示例以查看实际操作。
错误似乎在这行拖拽函数中:
d3.select(this).attr("transform", "translate("+(pos[0])+","+(pos[1])+")")
编辑
我尝试更新 STOP 函数以将起始值更新为
d3.select(this).attr("transform", function(d){
d.x += d3.event.x;
d.y += d3.event.y;
return "translate("+d3.event.x+","+d3.event.y+")"
})
现在,如果我在拖动开始时将 d.x, d.y 放在控制台中,输出会显示
x: 640 y: 299
但盒子总是从初始位置开始。我很困惑
感谢您的帮助!
【问题讨论】:
-
之所以总是从初始位置开始是因为初始位置永远不会改变。
x和y永远不会改变。您只需使用翻译转换位置,但每次您开始拖动时,转换都会从初始的x和y开始。 -
是的。这是对的。如何解决?
-
我已经根据小提琴中的代码进行了回答,这与问题中的代码不同(
g元素的初始转换)。我已经将代码从小提琴带到了问题中,因为它是我为答案构建的。不过,我看到您编辑了问题以删除这部分代码。如果我的回答解决了您的问题,为了保持一致性,我可能会对其进行编辑。主题和初始转换是我在下面解决的问题的两个部分。
标签: javascript d3.js