How frequently is D3 drag event triggered?

2019-08-02 19:07发布

I have a very general low level question about dragging. I am specifically interested in learning what exactly determines when a drag event is triggered in D3.js v4. For example, if I move a dragged object very slowly, a drag event will fire each pixel I move. However, if I move fairly fast, the drag event is not triggered in a one-to-one correlation with the amount of pixels I have moved.

I am currently researching this issue, primarily with the Chrome Dev Performance tab; I figure this will (hopefully) give me some insight. I am also aware that there are debouncing functions which can limit the amount of times an event is called; however, I don't know or see that D3 has this. I am thinking that the reason for the decreased calls to drag has something to do with something perhaps internal in Chrome and that perhaps it just uses some sort of algorithm to call drag based on how fast the mouse moves. This seems to be the most likely answer, but if anyone can give me some insight as to how exactly this behavior is determined, I would be greatly appreciative.

One last thing: I am also aware that sometimes when you move the mouse cursor so quickly that it 'exits' the object you are dragging, then the drag event should not be called. However, even when I don't 'leave' the object I am dragging, there are still less calls to drag based on how quickly I move the mouse cursor.

p.s. while I am using D3, this issue may very well just have to do with dragging in general and not be anything specific to D3...

1条回答
Luminary・发光体
2楼-- · 2019-08-02 19:55

The issue you're seeing has little to do with D3, it's a general JavaScript behaviour or, better yet, a browser-related behaviour: what you're seeing is a feature of mousemove.

If you look at the D3 API, you'll see that the "drag" event uses mousemove (or touchmove for touch devices):

drag - after an active pointer moves (on mousemove or touchmove).

Now comes the important information: mousemove is generated by the browser. More important than that, the browser is not obligated to generate the event by any specific rate, be it related to distance or time. Also, other factors may influence the frequency of mousemove, as the hardware you're using for instance.

So, if we assume (just for simplification) that the browser generates a mousemove event every 100ms, you have a simple explanation for the behaviour you described:

Given that speed = distance / time, if you move your mouse faster, you'll have less events from point A to B (that is, the distance from a mousemove event to the next will be bigger). If you move your mouse slower, you'll have more events from point A to B (that is, the distance from a mousemove event to the next will be smaller). If you move your mouse in a speed less than 1px/100ms (in our hypothetical scenario), you'll have 1 event per pixel.

Finally, here is a very simple demo showing it. Click and drag anywhere in the SVG:

var count = 0;
d3.select("svg").call(d3.drag().on("start", function() {
  console.log("drag started")
}).on("drag", function() {
  ++count; 
  console.log("drag event " + count)
}).on("end", function() {
  count = 0;
  console.log("drag ended")
}))
.as-console-wrapper { max-height: 20% !important;}
svg {
  border: 1px solid black;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>

查看更多
登录 后发表回答