Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
mbostock opened this issue Jun 16, 2020 · 1 comment
Open
Labels

Comments

@mbostock
Copy link
Member

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
Copy link
Member

Fil commented Jun 17, 2020

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:

  • setting the subject when the gesture starts (could be added easily);
  • having an arbitrary storage for the transform's location (instead of this.property(__zoom), allowing to store the transforms in the datum) [linked to the previous point]
  • mixing two zoom behaviors on the same node (https://observablehq.com/d/bf23cdda80dd75bb where I'm doing both zoom and "drag as zoom" would not be doable cleanly in canvas, as both behaviors would claim the canvas node's __zoom property) [linked to the previous point]

Related: d3/d3-selection#191

@Fil Fil added the idea label Jul 10, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

2 participants