d3 / d3-drag

Drag and drop SVG, HTML or Canvas using mouse or touch input.

Home Page:https://d3js.org/d3-drag

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Click event not firing if drag enables with simulation

richburdon opened this issue · comments

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]);

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

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