d3 / d3-zoom

Pan and zoom SVG, HTML or Canvas using mouse or touch input.
https://d3js.org/d3-zoom
ISC License
507 stars 143 forks source link

Does not receive "end" event after pressing right mouse button during drag & drop with left button #198

Closed kapulkin closed 3 years ago

kapulkin commented 4 years ago

I bind brush tool to zoom events with left mouse button. Also I bind drag & drop logic to zoom events with right button pressed. You could look here: https://viete.io/a170102c-e7b6-11e9-b4f9-9600001cf28e

To reproduce:

  1. Open https://viete.io/a170102c-e7b6-11e9-b4f9-9600001cf28e
  2. Start make selection by moving mouse on white space with left button pressed.
  3. Don't release mouse left button and press right button additionally
  4. Release right button and move mouse with left button pressed little more.
  5. Release mouse left button.
  6. Zoom end or start events will not occur anymore. And selection and drag & drop functionality become broken.

2019-12-30_00-46-05

I use code below to initialize zoom:

  async mounted () {
    const self = this

    select(this.selectionToolSelector)
      .call(
        this.zoomTool = zoom()
          .scaleExtent([1 / 20, 5])
          .filter(() => { return !event.ctrlKey })
          .on('start', self.zoomStart)
          .on('zoom', self.zoomed)
          .on('end', self.zoomEnd)
          // TODO: listen zoom on end to open contextMenu
      )

I use nuxt and d3 of versions: "nuxt": "^2.9.2" "d3": "^5.11.0"

kapulkin commented 4 years ago

I applied already my fork https://github.com/kapulkin/d3-zoom at https://viete.io/a170102c-e7b6-11e9-b4f9-9600001cf28e, so you will not be able to reproduce the bug there.

SilverIrbis commented 4 years ago

Hi! @kapulkin Excuse me, may I ask, how do you combined zoom with the brush? I mean - how did you bind brush on left mouse button? I have a similar task now, but Im new at d3 and kinda stuck with it

Fil commented 4 years ago

I'm sorry I'm not able to reproduce the issue. Could you try and isolate it in a simple page (a block or notebook?).

I'm also surprised that .filter(() => { return !event.ctrlKey }) works, as variable event doesn't appear to be defined.

To read the mouse buttons and filter the zoom start accordingly, you might want to test d3.event.buttons (https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons).

kapulkin commented 4 years ago
  1. Look, please, on suggested change in pull request. The fix really improve logic, so it is acceptable to merge it.

  2. I import d3.event as event, that's why the code works.

Fil commented 4 years ago

It would really help to be able to reproduce the issue with readable code. I've spent quite some time on it now, but I wasn't able to figure out how to make the gesture's "active" count go beyond 1. I can only suppose that there is a conflict between event listeners.

Also, I don't dispute that your patch helps in your case, and that it makes sense to unregister mouseup only if the active count is down to 0, but I'm not sure why we would unregister mousemove.zoom and restore drag if active > 0? In other words, if the gesture has somehow not been closed by that mouseup event, then everything should wait for the real end of the gesture?

amannn commented 4 years ago

(moved to https://github.com/d3/d3-zoom/issues/222)

Fil commented 4 years ago

@amannn I'm promoting your question to its own separate issue in https://github.com/d3/d3-zoom/issues/222

amannn commented 4 years ago

@Fil Thank you for your help!