在 D3 热图中集成 D3 Band zoom

To integrate D3 Band zoom in D3 heatmap

这里我要整合D3 Band zoom in D3 Heatmap with resettable zoom. The red band appears while dragging, but it didn't zoom. I think, there some issue in zoom function, but i couldn't track it yet. Please check out my fiddle.

缩放功能:

function zoom() {

    //recalculate domains
  if(zoomArea.x1 > zoomArea.x2) {
      x.domain([zoomArea.x2, zoomArea.x1]);
    } else {
      x.domain([zoomArea.x1, zoomArea.x2]);
    }

    if(zoomArea.y1 > zoomArea.y2) {
      y.domain([zoomArea.y2, zoomArea.y1]);
    } else {
      y.domain([zoomArea.y1, zoomArea.y2]);
    }

    var t = svg.transition().duration(750);
    t.select(".x.axis").call(scale[X]);
    t.select(".y.axis").call(scale[Y]);
}

请提出解决方法。提前谢谢你。

这是一个可能的解决方案。

首先,放弃 canvas。

改用以下结构:

<svg>
  <g id="x axis">
    // ...
  </g>
  <g id="y axis">
    // ...
  </g>
  <svg id="imageContainer" viewbox="0 0 heatmapDim[0] heatmapDim[1]">
    <image xlink:href="yourHeatmap"/>   
  </svg>
</svg>

这里的关键是使用第二个<svg>(#imageContainer)的viewBox属性。这将允许您在图像上定义子窗口

并修改你的缩放比例

function zoom() {
        
     //recalculate domains
      var x0,x1,y0,y1;
  
      if(zoomArea.x1 > zoomArea.x2) {
          x0 = zoomArea.x2;
          x1 = zoomArea.x1;
        } else {
          x0 = zoomArea.x1;
          x1 = zoomArea.x2;
        }
        
        if(zoomArea.y1 > zoomArea.y2) {
          y0 = zoomArea.y2
          y1 = zoomArea.y1;
        } else {
          y0 = zoomArea.y1;
          y1 = zoomArea.y2;
        }
        
        
        d3.select("#imageContainer").attr("viewBox",x0 + " " + y0 + " " + x1 + " " + y1);
       
  }

这应该可以解决问题,还没有测试过,你的 fiddle 太大了,没用。

这是一个潜在的基于 canvas 的解决方案。

您可以修改缩放功能以强制使用图像的子矩形重新绘制

context.drawImage(image,sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);

然后给出 sx,sy 选择矩形的左上角坐标,sWidth,sHeight 选择矩形的宽度和大小。

dx,dy,dWidth,dHeight 在你的情况下是不变的,0,0,canvasWidth,canvasSize

您可能需要修改 createImageObj 以也使用 drawImage 而不是 putImage。我不熟悉 canvas 所以你需要检查这一点。

希望这对您有所帮助。

作为参考,MDN 文档在 drawImage