d3 / d3-drag

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

Click event not firing if drag enables with simulation #69

Closed richburdon closed 4 years ago

richburdon commented 4 years ago

I have seen a number of issues relating to this, but I have a different case. I'm registering a global drag handler on the outer canvas, and a click event listener on the actual nodes -- which are updated by the simulation.

If drag is registered then the click event never fires. If I remove it, then it does. Also if the nodes are not controlled by the simulation it also fires properly.

Is it possible that the tick update interferes with the event handling?

  const update = () => {
    d3.select(nodes.current)
      .selectAll('circle')
        .data(items)
        .join('circle')
          .attr('cx', (d) => d.x)
          .attr('cy', (d) => d.y)
          .attr('r', 20)
          .on('click', () => console.warn('click:', d3.event))
  }

  useEffect(() => {
    setSimulation(d3.forceSimulation()
      .nodes(items)
      .on('tick', update)
      .on('end', () => {
        log('end')
      })
      .force('charge', d3.forceManyBody().strength(-100)));
  }, [items]);

  useEffect(() => {
    d3.select(nodes.current)
      .call(d3.drag()
        .container(nodes.current)
        .subject(() => simulation.find(d3.event.x, d3.event.y))
        .on('start', () => {
          log('drag:start:', d3.event)
          if (!d3.event.active) {
            simulation.alphaTarget(0.3).restart();
          }

          const node = d3.event.sourceEvent.target;
          d3.select(node).raise();

          d3.event.subject.fx = d3.event.subject.x;
          d3.event.subject.fy = d3.event.subject.y;
        })
        .on('drag', () => {
          log('drag:', d3.event)
          d3.event.subject.fx = d3.event.x;
          d3.event.subject.fy = d3.event.y;
        })
        .on('end', () => {
          if (!d3.event.active) {
            simulation.alphaTarget(0);
          }

          log('drag:end:', d3.event)
          d3.event.subject.fx = null;
          d3.event.subject.fy = null;
        }));
  }, [simulation]);
mbostock commented 4 years ago

Please see the following notebook for how to use click & drag:

https://observablehq.com/@d3/click-vs-drag