admin管理员组

文章数量:1410682

I have a simple drag event - and if a certain condition is met, I'd like to force cancel the drag currently under way (basically as if you were doing a mouseup).

Something like so:

var drag_behavior = d3.behavior.drag()
.on("drag", function() {
    if(mycondition){
       // cancel the drag event
    }
});

EDIT:

the goal is simply to prevent people from dragging a world map outside certain boundaries in such a way that renders the map in mid-ocean (details below).

Current map code:

var width = window.innerWidth
var height = window.innerHeight

var projection = d3.geo.mercator()
    .scale((width + 1) / 2 / Math.PI)
    .translate([width / 2, height/1.5])
    .precision(.1);

var path = d3.geo.path()
    .projection(projection);

var drag_behavior_map = d3.behavior.drag()
.on("drag", function() {
    drag_click = true //used later to prevent dragend to fire off a click event
    d3.event.sourceEvent.stopPropagation();

    // original idea
    // if(worldmap_left_boundary > 0 || worldmap_right_boundary < screen.height){
    //    cancel or limit the drag here
    // }
});

var svg = d3.select("#map").append("svg")
    .attr("width", width)
    .attr("height", height)
.call(drag_behavior_map)

Basically this should not be possible.

I have a simple drag event - and if a certain condition is met, I'd like to force cancel the drag currently under way (basically as if you were doing a mouseup).

Something like so:

var drag_behavior = d3.behavior.drag()
.on("drag", function() {
    if(mycondition){
       // cancel the drag event
    }
});

EDIT:

the goal is simply to prevent people from dragging a world map outside certain boundaries in such a way that renders the map in mid-ocean (details below).

Current map code:

var width = window.innerWidth
var height = window.innerHeight

var projection = d3.geo.mercator()
    .scale((width + 1) / 2 / Math.PI)
    .translate([width / 2, height/1.5])
    .precision(.1);

var path = d3.geo.path()
    .projection(projection);

var drag_behavior_map = d3.behavior.drag()
.on("drag", function() {
    drag_click = true //used later to prevent dragend to fire off a click event
    d3.event.sourceEvent.stopPropagation();

    // original idea
    // if(worldmap_left_boundary > 0 || worldmap_right_boundary < screen.height){
    //    cancel or limit the drag here
    // }
});

var svg = d3.select("#map").append("svg")
    .attr("width", width)
    .attr("height", height)
.call(drag_behavior_map)

Basically this should not be possible.

Share edited Jan 6, 2014 at 4:17 L-R asked Jan 2, 2014 at 3:00 L-RL-R 1,2321 gold badge19 silver badges40 bronze badges 7
  • 2 Describe what you mean by "cancel the drag event" -- you can always just choose to return from the event listener method without making any changes. Or you can add conditions to the changes you make, as in this example which bounds how far a node can be dragged by applying a max/min function. – AmeliaBR Commented Jan 2, 2014 at 4:24
  • How did things work out for you? – meetamit Commented Jan 5, 2014 at 15:04
  • hey @meetamit actually not that good. I don't think "canceling" the drag event is going to work, I haven't seen anyone doing it this way. It doesn't seem to be possible to interrupt a drag progammatically, at least I tried your 2 suggestions + variants and it did not fire at all. the suggestion from AmeliaBR might be better suited, although I haven't been able to find code references for this. I have a simple world map that's draggable/zoomable, but I don't want people to drag the map outside of the limits of its projection! I'll update with some code in my original question. – L-R Commented Jan 5, 2014 at 22:21
  • Constraining the panning is similar to the link @AmeliaBR provided, but in your case you'd constrain the geo projection's rotation rather than the x and y coordinates, still using Math.min and Math.max. For more specific help, you should show the code you wrote for dragging the map –– inside .on("drag", function() {}); –– even if it doesn't yet account for limiting the dragging. – meetamit Commented Jan 6, 2014 at 4:02
  • 2 Check out this example to see how to rotate the projection on drag. The projection is different than the one you're using, but same formula should work. – meetamit Commented Jan 6, 2014 at 4:23
 |  Show 2 more ments

1 Answer 1

Reset to default 5

Inside the drag event function, you can use mycondition to decide whether or not to update the dragged element's position. Not updating the position essentially means stopping the drag.

You could also unsubscribe from the drag event:

var drag_behavior = d3.behavior.drag()
  .on("drag", function() {
    if(mycondition) {
       // cancel the drag event
       drag_behavior.on("drag", null);
    }
  });

Note, there would still be a dragend event, unless you unsubscribe that one too.

Alternatively –– though I'm not totally familiar with triggering native events and how that affects d3.behavior.drag() –– you can try triggering a native mouseup event and see what happens.

var drag_behavior = d3.behavior.drag()
  .on("drag", function() {
    if(mycondition) {
      // "this" is the dragged dom element
      this.dispatchEvent(new Event('mouseup'))
    }
  });

本文标签: javascriptd3js force cancel a drag eventStack Overflow