Reputation: 157
How can I prevent the svg's "g" element from overlapping on the other "g" elements when I drag the element to switch/change its position. Below is the link to the code.
https://jsfiddle.net/3jxqgjcL/
var group = svg.selectAll('g')
.data(rectangles)
.enter().append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
group.append("rect")
.attr("x", function(d) { return d.x; })
.attr("y", function(d) { return d.y; })
.attr("height", 60)
.attr("width", 300)
.style("fill", function(d, i) { return color(i); });
group.append("text")
.attr("x", function(d) { return d.x; })
.attr("y", function(d) { return d.y; })
.attr("text-anchor", "start")
.style("fill", "steelblue")
.text("Close");
function dragstarted(d) {
d3.select(this).raise().classed("active", true);
}
function dragged(d) {
d3.select(this).select("text")
.attr("y", d.y = d3.event.y);
d3.select(this).select("rect")
.attr("y", d.y = d3.event.y);
}
function dragended(d) {
d3.select(this).classed("active", false);
}
Upvotes: 2
Views: 1432
Reputation: 102174
Your question is not exactly clear. I'm assuming that by prevent the svg's "g" element from overlapping you want to rearrange the groups when you release one of them.
That being the case, you can get all the <g>
elements in the dragended
function, sort them and translate them according to their indices:
function dragended(d) {
d3.select(this).classed("active", false);
var theseGroups = svg.selectAll(".groups").sort(function(a, b) {
return d3.ascending(a.y, b.y);
});
theseGroups.attr("transform", function(d, i) {
return "translate(" + margin.left / 2 + "," + (d.y = barHeight * i) + ")";
})
}
Here is a demo:
var margin = {
top: 10,
right: 10,
bottom: 30,
left: 10
},
width = 500 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom
distance = 0, barHeight = 75, i = 0;
function yAxis() {
if (i == 0) {
i++;
return 2;
} else {
distance = parseInt(barHeight) * i;
i++;
return distance;
}
}
var rectangles = d3.range(5).map(function() {
return {
x: 5,
y: Math.round(yAxis())
};
});
var color = d3.scaleOrdinal(d3.schemeCategory10);
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
var group = svg.selectAll('g')
.data(rectangles)
.enter().append("g")
.attr("class", "groups")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")"
})
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
group.append("rect")
.attr("height", 60)
.attr("width", 300)
.style("fill", function(d, i) {
return color(i);
});
group.append("text")
.attr("text-anchor", "start")
.style("fill", "steelblue")
.text("Close");
function dragstarted(d) {
d3.select(this).raise().classed("active", true);
}
function dragged(d) {
d3.select(this).attr("transform", "translate(" + margin.left / 2 + "," + (d.y = d3.event.y) + ")");
}
function dragended(d) {
d3.select(this).classed("active", false);
var theseGroups = svg.selectAll(".groups").sort(function(a, b) {
return d3.ascending(a.y, b.y);
});
theseGroups.attr("transform", function(d, i) {
return "translate(" + margin.left / 2 + "," + (d.y = barHeight * i) + ")";
})
}
svg {
border: 1px solid #000;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
Upvotes: 1