首页 > 解决方案 > 如何使用 d3 zoomBehavior 检测用户的平移和缩放?

问题描述

我正在使用 d3.zoomBehavior 在地图上启用平移和缩放。它工作正常。我还编写了代码以将地图重新​​定位在焦点项目上,这也很有效。如果用户手动缩放或平移(检查地图控件是否“脏”),我希望禁用此“自动重新定位”。)

当用户手动移动地图时,如何访问事件?

我尝试访问拖动、滚轮和缩放事件:

d3.select("svg").call(this.zoomBehavior).on("wheel", () => {
  console.log("user has zoomed with wheel"); // never gets called
}).on("drag", () => {
  console.log("user has panned map"); // never gets called
}).on("zoom", () => {
  console.log("zoom event"); // gets called even when the map is autofocusing -- not what I need.
});

我可以绑定选择上的哪些事件来确定用户何时操作缩放和平移?

标签: javascriptd3.jsevents

解决方案


在您的缩放功能中,检查是否d3.event.sourceEvent已定义。触发的缩放selection.call(zoom.transform,someZoomTransform)具有 null 的 sourceEvent。此外,sourceEvent.type可以提供有关事件类型的附加信息(例如:滚轮、鼠标移动)。

这是 Bostock 的画笔和缩放示例中使用的方法。手动刷会触发缩放的程序化更新,手动缩放会触发画笔的程序化更新:该示例需要检测什么是手动与程序化缩放/刷子以避免无限循环。

下面的程序化缩放应用于 svg(覆盖片段预览窗口),但您也可以平移/缩放。通过检查 sourceEvent 是否为 null,我们可以查看缩放是由用户启动还是以编程方式启动:

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>


推荐阅读