Reputation: 7143
I'm new to d3.js, and just trying to learn. How do I make a g draggable? I have a g with a rect and text in it. I want to drag both objects together. Here is my plunkr:
I've tried googling for samples but they are overly complex and I'm having difficulty understanding most of them.
let svg = d3.select("body").append("svg")
.attr("width", 960)
.attr("height", 500);
let g = svg.append("g")
.on("mouseover", function(d) {
d3.select(this)
.style("cursor","pointer");
d3.select(this).select("rect")
.style("fill", "#325d81");
})
.on("mouseout", function(d){
d3.select(this)
.style("cursor","default");
d3.select(this).select("rect")
.style("fill","#4682b4");
});
Thanks!
Upvotes: 1
Views: 1509
Reputation: 3488
You can transform the <g>
element, first establishing the onmousedown coordinates.
Try the below:
<!DOCTYPE html>
<html>
<head>
</head>
<meta charset="utf-8">
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
function wrap(text, width) {
text.each(function() {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.1, // ems
y = text.attr("y"),
dy = parseFloat(text.attr("dy")),
tspan = text.text(null).append("tspan").attr("x", 10).attr("y", y).attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > (width-7.5)) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan").attr("x", 10).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
}
}
});
}
let longText = "Now is the time for all good men to come to the aid of their country and asds and stuff an such jdsfj kljasdkflj kdsfj sdfkj klsjd kljdsf lk sdfj lkdfs jlk sd a";
var coordX
var coordY
let svg = d3.select("body").append("svg")
.attr("width", 960)
.attr("height", 500)
let g = svg.append("g")
.on("mouseover", function(d) {
d3.select(this)
.style("cursor","pointer");
d3.select(this).select("rect")
.style("fill", "#325d81");
})
.on("mouseout", function(d){
d3.select(this)
.style("cursor","default");
d3.select(this).select("rect")
.style("fill","#4682b4");
})
.on('mousedown', function () {
coordX= d3.mouse(this)[0];
coordY= d3.mouse(this)[1];
})
.call(d3.drag()
.on("drag", dragged))
let rect2 = g.append("rect")
.attr("x",5)
.attr("y",5)
.attr("rx",20)
.attr("ry",20)
.attr("width",300)
.attr("height",150)
.style("fill","#4682b4")
.style("stroke","black")
.style("stroke-width",5)
.style("opacity",0.5)
;
var txt = g.append('text')
.text(longText) //<-- our super long text
.attr('x', 0)
.attr('y', 30)
.attr('dy', '.71em')
.style('fill', 'white')
.call(wrap, 300); //<-- wrap it according to our width
var height = txt.node().getBBox().height + 40; //<-- get our height plus a margin
rect2.attr('height', height); //<-- change our rect
function dragged() {
var transX=d3.event.x-coordX
var transY=d3.event.y-coordY
d3.select(this).attr("transform","translate("+transX+" "+transY+")")
}
</script>
</body>
</html>
Upvotes: 3
Reputation: 126
because you did not datanum your selection, function d is always undefined.you can try
function dragged(d) {
var x=d3.event.x, y=d3.event.y
d3.select(this).select("text")
.attr("x", x)
.attr("y", y);
d3.select(this).select("rect")
.attr("x",x)
.attr("y",y);
}
Upvotes: 0