Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dispatching drag-end event

I want to programmatically fire the "end" event of d3-drag. I have some circles and have the drag-handling of them implemented like so:

...
.call(d3.drag()
     .on("drag", function () {...})
     .on("end", function () {...})
)

Now, later in my code, I would like to trigger the "end" part of this programmatically.

I have already tried something like this:

d3.select("#myID").dispatch("end");
d3.select("#myID").dispatch("dragend");
d3.select("#myID").call(d3.drag().dispatch("end"));
like image 365
Jonas Avatar asked Oct 29 '20 14:10

Jonas


People also ask

What is a drag event?

The DragEvent interface is a DOM event that represents a drag and drop interaction. The user initiates a drag by placing a pointer device (such as a mouse) on the touch surface and then dragging the pointer to a new location (such as another DOM element).

Which event is fired when an element is dragged?

The drag event is fired every few hundred milliseconds as an element or text selection is being dragged by the user.

How do you find a drag event?

On the “mouse up” event, the value of drag variable is checked. If the value is true, a “drag” event has occurred and the output is displayed in the console. If the value is 'false' which means there has been no “mouse move” event which also implies that a “click” event had occurred.


Video Answer


1 Answers

If you don't need to generate any actual event data, and I understand the question correctly, you can do this relatively easily without d3.dispatch directly. The below will give you this and the node data itself (in d3v5 it will also give you i and nodes).

D3v5 and earlier

In d3v5 and earlier, the signatures for a function passed to selection.each() and drag.on() were the same. In this case you can easily assign the function to a variable and pass it to both. Alternatively, you could access the drag event function with drag.on("typeName").

Here's a quick example:

var svg = d3.select("body")
  .append("svg")
  .attr("width",500)
  .attr("height",300);
  
var data = [{x:40,y:100},{x:250,y:100}];

var circles = svg.selectAll(null)
  .data(data)
  .enter()
  .append("circle")
  .attr("r", 10)
  .attr("cx", function(d) { return d.x; })
  .attr("cy", function(d) { return d.y; })
  .attr("fill", function(d,i) {
    return ["steelblue","crimson"][i]
  })

var drag = d3.drag()
  .on("drag", function(d) {
    d.x = d3.event.x; d.y = d3.event.y;
    d3.select(this)
      .attr("cx", d.x)
      .attr("cy", d.y);
  })
  .on("end", function(d) {
     console.log(d.x+","+d.y);
     d3.select(this)
       .transition()
       .attr("r", 30)
       .transition()
       .attr("r", 10);
  })
  
circles.call(drag);

d3.select("button").on("click", function() {
  var circle = d3.select("circle")
    .each(drag.on("end"));
})
circle {
   cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<button>Trigger Drag End On Blue Circle</button>

D3v6

In d3v6 the signatures of functions passed to selection.each() and drag.on() are different. The datum is the first parameter of the former and the second parameter of the latter. So we could use Function.apply() within selection.each() to trigger the end function and pass the proper this and d while passing null for the event data.

var svg = d3.select("body")
  .append("svg")
  .attr("width",500)
  .attr("height",300);
  
var data = [{x:40,y:100},{x:250,y:100}];

var circles = svg.selectAll(null)
  .data(data)
  .enter()
  .append("circle")
  .attr("r", 10)
  .attr("cx", function(d) { return d.x; })
  .attr("cy", function(d) { return d.y; })
  .attr("fill", function(d,i) {
    return ["steelblue","crimson"][i]
  })

var drag = d3.drag()
  .on("drag", drag)
  .on("end", dragend)

circles.call(drag);

d3.select("button").on("click", function() {
   var circle = d3.select("circle")
    .each(function(d) { 
       dragend.apply(this,[null,d]) 
    })
})


function dragend(event,d) {
  console.log(d.x+","+d.y);
  d3.select(this)
    .transition()
    .attr("r", 30)
    .transition()
    .attr("r", 10);
}
function drag(event,d) {
  d.x = event.x; d.y = event.y;
  d3.select(this)
    .attr("cx", d.x)
    .attr("cy", d.y);
}
circle {
   cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.0.0/d3.min.js"></script>
<button>Trigger Drag End On Blue Circle</button>
like image 142
Andrew Reid Avatar answered Sep 19 '22 12:09

Andrew Reid