admin管理员组

文章数量:1391925

I want to make a draggable <g> element containing a <circle> and a <text> but I failed.

Now I have this code:

var margin = {top: -5, right: -5, bottom: -5, left: -5},
    width = 1960 - margin.left - margin.right,
    height = 1500 - margin.top - margin.bottom;


var drag = d3.behavior.drag()
    .origin(function(d) { return d; })
    .on("dragstart", dragstarted)
    .on("drag", dragged)
    .on("dragend", dragended);

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom);


var dotContainer = svg.append("g")
    .attr("class", "dotContainer")
    .datum({x:220, y:120})
    .attr("x", function(d) { return d.x; })
    .attr("y", function(d) { return d.y; })
    .call(drag);

var dot = dotContainer.append("circle")
    .attr("class", "dot")
    .datum({x:220, y:120})
    .attr("cx", function(d) { return d.x; })
    .attr("cy", function(d) { return d.y; })
    .attr("r", 5).call(drag);

var text =  dotContainer.append("text")
    .datum({x:220, y:120})
    .attr("x", function(d) { return d.x; })
    .attr("y", function(d) { return d.y; })
    .text('Title');  



function dragstarted(d) {
  d3.event.sourceEvent.stopPropagation();
  d3.select(this).classed("dragging", true);
}

function dragged(d) {
  d3.select(this).attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);
}

function dragended(d) {
  d3.select(this).classed("dragging", false);
}
<script src=".v3.min.js"></script>

I want to make a draggable <g> element containing a <circle> and a <text> but I failed.

Now I have this code:

var margin = {top: -5, right: -5, bottom: -5, left: -5},
    width = 1960 - margin.left - margin.right,
    height = 1500 - margin.top - margin.bottom;


var drag = d3.behavior.drag()
    .origin(function(d) { return d; })
    .on("dragstart", dragstarted)
    .on("drag", dragged)
    .on("dragend", dragended);

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom);


var dotContainer = svg.append("g")
    .attr("class", "dotContainer")
    .datum({x:220, y:120})
    .attr("x", function(d) { return d.x; })
    .attr("y", function(d) { return d.y; })
    .call(drag);

var dot = dotContainer.append("circle")
    .attr("class", "dot")
    .datum({x:220, y:120})
    .attr("cx", function(d) { return d.x; })
    .attr("cy", function(d) { return d.y; })
    .attr("r", 5).call(drag);

var text =  dotContainer.append("text")
    .datum({x:220, y:120})
    .attr("x", function(d) { return d.x; })
    .attr("y", function(d) { return d.y; })
    .text('Title');  



function dragstarted(d) {
  d3.event.sourceEvent.stopPropagation();
  d3.select(this).classed("dragging", true);
}

function dragged(d) {
  d3.select(this).attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);
}

function dragended(d) {
  d3.select(this).classed("dragging", false);
}
<script src="https://d3js/d3.v3.min.js"></script>

<circle> element is perfectly draggable, ok. But I need to apply dragging to the whole <g> element to drag my circle together with the <text> element.

How can I do this?

When I apply call(drag) to dotContainer like this

dotContainer.call(drag);

then nothing works.

Share Improve this question edited Dec 14, 2017 at 14:57 altocumulus 21.6k13 gold badges64 silver badges86 bronze badges asked Dec 14, 2017 at 14:43 Barney GumbleBarney Gumble 751 silver badge6 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 8

You should rewrite your dotContainer variable this way:

var dotContainer = svg.append("g")
    .attr("class", "dotContainer")
    .datum({x:220, y:120})
    .attr("transform", function(d) { return 'translate(' + d.x + ' '+ d.y + ')'; })
    .call(drag);

Remove .call(drag) for dot variable and rewrite dragged function like this:

function dragged(d) {
  d.x += d3.event.dx;
  d.y += d3.event.dy;

  d3.select(this).attr("transform", function(d,i){
    return "translate(" + [ d.x,d.y ] + ")"
  });
}

Thus we use transform attribute for an initial container position and for the position update during the dragging.

Check demo in the hidden snippet:

var margin = {top: -5, right: -5, bottom: -5, left: -5},
    width = 1960 - margin.left - margin.right,
    height = 1500 - margin.top - margin.bottom;


var drag = d3.behavior.drag()
    .origin(function(d) { return d; })
    .on("dragstart", dragstarted)
    .on("drag", dragged)
    .on("dragend", dragended);

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom);


var dotContainer = svg.append("g")
    .attr("class", "dotContainer")
    .datum({x:20, y:20})
    .attr("transform", function(d) { return 'translate(' + d.x + ' '+ d.y + ')'; })
    .call(drag);

var dot = dotContainer.append("circle")
    .attr("class", "dot")
    .datum({x:20, y:20})
    .attr("cx", function(d) { return d.x; })
    .attr("cy", function(d) { return d.y; })
    .attr("r", 5)

var text =  dotContainer.append("text")
    .datum({x:20, y:20})
    .attr("x", function(d) { return d.x; })
    .attr("y", function(d) { return d.y; })
    .text('Title');  

function dragstarted(d) {
  d3.event.sourceEvent.stopPropagation();
  d3.select(this).classed("dragging", true);
}

function dragged(d) {
  d.x += d3.event.dx;
  d.y += d3.event.dy;
            
  d3.select(this).attr("transform", function(d,i){
    return "translate(" + [ d.x,d.y ] + ")"
  });
}

function dragended(d) {
  d3.select(this).classed("dragging", false);
}
.dotContainer {
  cursor: move;
}
<script src="https://d3js/d3.v3.min.js"></script>

本文标签: javascriptHow can I drag group (g) element in D3jsStack Overflow