score:1

Accepted answer

In your zoomed function, check to see if d3.event.sourceEvent is defined. A zoom triggered by selection.call(zoom.transform,someZoomTransform) has a sourceEvent of null. Also, sourceEvent.type can provide additional information on the type of event (eg: wheel, mousemove).

This is the approach used in Bostock's brush and zoom example. Manually brushing triggers a programmatic update of the zoom and manually zooming triggers a programmatic update of the brush: the example needs to detect what is a manual vs programmatic zoom/brush to avoid an infinite loop.

Below a programmatic zoom is applied to the svg (covers the snippet preview window), but you can also pan/zoom. By checking to see if sourceEvent is null, we can see if a zoom was initiated by the user or programmatically:

var svg = d3.select("body")
  .append("svg")
  .attr("width", 600)
  .attr("height", 500);

var zoom = d3.zoom()
  .on("zoom", function() {
      if(d3.event.sourceEvent) {
        console.log("not programmatic zoom");
      }
      else {
        console.log("programmatic zoom");
      }
      
  })

svg.call(zoom);
svg.call(zoom.transform,d3.zoomIdentity);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

score:0

You can check with this condition

 const action = d3.event.type === "zoom" && d3.event?.sourceEvent?.type === "mousemove" ? "PAN": "ZOOM";

Related Query

More Query from same tag