d3 / d3-drag

Drag and drop SVG, HTML or Canvas using mouse or touch input.
https://d3js.org/d3-drag
ISC License
335 stars 61 forks source link

Use native events (*element*.dispatchEvent) instead of d3-dispatch? #73

Open mbostock opened 4 years ago

mbostock commented 4 years ago

d3-drag, d3-zoom and d3-brush store state on the DOM elements they are applied to. Would then it not make more sense to listen to events on the DOM elements, rather than the behaviors? For example, instead of:

  return d3.select(context.canvas)
    .call(zoom(projection)
        .on("zoom.render", () => render(land110))
        .on("end.render", () => render(land50)))
    .call(() => render(land50))
    .node();

You might say:

  return d3.select(context.canvas)
    .call(zoom(projection))
    .on("zoom.render", () => render(land110))
    .on("zoomend.render", () => render(land50)))
    .call(() => render(land50))
    .node();

By using native DOM events, these events could bubble and be cancelled, giving more flexibility in how the events are handled.

This technique could apply to d3-transition events, too.

One awkward aspect is that there’s a single namespace of events. In particular, there’s already a native drag event, so I’m not sure what we should call the D3 drag event (d3:drag?). Also, this would change the structure of the events, because any additional properties would need to live on event.details rather than on the event itself.

Another awkward aspect is that d3-dispatch would still be needed, presumably, for d3-force, since d3.forceSimulation is stateful. (You’re listening to the simulation itself.) Although, we could implement the EventTarget interface for d3.forceSimulation, too, rather than using d3-dispatch.

Is this something we want? And if so, if we’re ditching d3.event in d3@6, is it worth doing this now?

Fil commented 4 years ago

I think it makes sense, but not sure that I fully grasp all the consequences or would know how to code this. If we want to do this, it would clearly be better to do it at once, rather than have two successive breaking changes in v6 then v7.

It's fun that you post this in d3-drag, as drag is the behavior that does not use the DOM to store state (it's usually stored in the datum through the subject method).

In fact, one tangential question I've had is whether d3-drag is necessary at all, given that dragging is but a subset of zooming (it's like d3.zoom().scaleExtent([1, 1]) with no wheel nor dblclick.). In concrete terms the only things we can't do currently with d3-zoom are:

Related: https://github.com/d3/d3-selection/issues/191