Chrome-使用 D3 缩放时的特定问题

Chrome-specific issue when using D3 zoom

我正在开发 D3 应用程序,遇到了一个奇怪的缩放问题,该问题出现在 Chrome 而不是 Firefox(这是我唯一测试过我的代码的浏览器)。我已将问题归结为下面的代码片段。

基本上,在某些情况下,当我在 canvas 元素上滚动时(使用鼠标的滚动按钮或笔记本电脑触控板上的两个手指),我定义的缩放处理程序不会被调用。但是,单击并拖动 canvas 以尝试平移它会成功调用缩放处理程序。

问题详情:

下面的代码在左上角创建了一个 canvas 元素(它不可见,因为它的不透明度为 0)。缩放元素将向控制台打印一条“缩放”消息。单击 canvas 将打印“单击”。您会发现,按原样使用代码,如果您单击该元素然后尝试滚动缩放,则不会打印“缩放”。您还可以 运行 JSFiddle 中的代码:https://jsfiddle.net/yr3jdvhw/37/

我想知道是什么导致了这个问题。正如我提到的,我可以将 canvas 的不透明度设置为非零值来避免该问题。但我真的很想知道根本原因。

<html>
  <head>
    <script src="https://d3js.org/d3.v5.min.js"></script>
  </head>
  <body>
    <canvas class="my-canvas"></canvas>
   
    <script>
      const myCanvas = d3.select(".my-canvas")
      .style('opacity', 0)
      .on('click', function () {
        console.log("click")
        let ctx = this.getContext('2d')
        const pixel = ctx.getImageData(0, 0, 1, 1)
      })
      .call(d3.zoom().on('zoom', () => {
        console.log("zooming")
      }))
      .call(function (s) {
        let ctx = s.node().getContext('2d')
        ctx.clearRect(0, 0, s.node().width, s.node().height)
      })
    </script>
  </body>
</html>

这是一个 Chrome 错误,我刚刚打开了一个关于它的 new issue,希望它能尽快得到修复。

根据我的调查,根本问题是它们确实在合成器级别处理轮子事件,并且当您的 canvas 减速时,它不再在合成器中采用正确的路径,因此不再被视为“车轮事件处理程序区域”。

当前调用 getImageData() 会使您的 canvas 减速,它从 GPU 转到 CPU 并停留在那里,这就是调用此方法导致问题的原因。同样,在您执行任何绘图操作之前,canvas 尚未移动到 GPU,因此这里也会重现错误。

请注意,希望在一些版本中 { willReadFrequently } 可以不使用标志,并且目前大多数 canvases 将始终加速。