当窗口大小调整时,D3缩放行为

d3 zoom behavior when window is resized

本文关键字:缩放 D3 窗口大小 调整      更新时间:2023-09-26

我使用D3来设置我的图表区域,利用可缩放的行为。该图表包括x轴和y轴。

当窗口调整大小时,图表区域应该是响应的。在这种情况下,我需要重置x轴和y轴域和窗口调整大小的范围。

窗口大小调整出现问题。我注意到缩放焦点在以下步骤之后不再与鼠标对齐:

  1. 首先在图表区域进行平移和缩放
  2. 然后调整窗口大小
  3. 然后再次平移和缩放图表区域

之后,上述问题发生了。查看下面有这个问题的文件

那么正确的处理方法是什么呢?我注意到一些关于这个问题的讨论,比如:

d3重置范围后保留刻度/平移

我尝试过这种方法,但我无法使用D3 V4 API使其工作。

主要思想是使用window.addEventListener来更新情节:

    window.addEventListener('resize', () => {
      // obtain the current transformation by calling the `d3.zoomTransform` function
      const t0 = d3.zoomTransform(
        chart.node());
      // obtain the client width by evaluating the `div` (class: `zoom-chart`)
      width = document.getElementById('zoom-chart').clientWidth;
      height = 480;
      // update the base scale
      baseX.range([0, width])
        .interpolate(d3.interpolateNumber);
      baseY.range([height, 0])
        .interpolate(d3.interpolateNumber);
      // update the view port
      vb = [0,0, width,height];
      chart  
        .attr('viewBox', vb);
        
      // replot with the original transform
      chart.call(zoom.transform, t0);
    });

我还在这里添加了整个解决方案:

const data = [
         {x:1 , y:1},
         {x:9 , y:1},
         {x:9 , y:9},
         {x:1 , y:9},
        ];
        
        var width = document.getElementById('zoom-chart').clientWidth;
        var height = 480;
        var baseX = d3.scaleLinear().domain([0,10])
            .range([0, width])
            .interpolate(d3.interpolateNumber);
        var baseY = d3.scaleLinear().domain([0,10])
            .range([height, 0])
            .interpolate(d3.interpolateNumber);
        var scaleX = baseX;
        var scaleY = baseY;
        const zoom = d3.zoom()
          .on('zoom', () => {
            const transform = d3.event.transform;
            scaleX = transform.rescaleX(baseX)
              .interpolate(d3.interpolateNumber)
            scaleY = transform.rescaleY(baseY)
              .interpolate(d3.interpolateNumber)
           
            render();
          });
        
        const chart = d3.select('#zoom-chart')
          .append('svg')
          .attr('class', 'chart')
          .call(zoom); 
         
        const rect = chart
          .append('rect')
          .attr('rx', 10).attr('ry', 10)
          .attr('x', 10).attr('y', 10)
          .attr('fill', '#00222b')
          .attr('width', width-20)
          .attr('height', height-20);
        const plot = chart
          .append('g')
          .attr('class', 'plot-area');
        function render() {
          plot.selectAll('.data')
            .data(data)
            .join(
              enter => enter.append('circle')
                .attr('class', 'data')
                .attr('r', 10)
                .attr('stroke', '#004455')
                .attr('stroke-width', 5),
              update => update,
              exit => exit.remove()
            )
            .attr('cx', d => scaleX(d.x))
            .attr('cy', d => scaleY(d.y));
        }
        
        window.addEventListener('resize', () => {
          const t0 = d3.zoomTransform(
            chart.node());
          width = document.getElementById('zoom-chart').clientWidth;
          height = 480;
          baseX.range([0, width])
            .interpolate(d3.interpolateNumber);
          baseY.range([height, 0])
            .interpolate(d3.interpolateNumber);
          vb = [0,0, width,height];
          chart  
            .attr('viewBox', vb);
            
          rect
            .attr('width', width-20)
            .attr('height', height-20);
            
          chart.call(zoom.transform, t0);
        });
        
        let vb = [0,0, width,height];
        chart  
          .attr('viewBox', vb);
          
        chart.call(zoom.transform, d3.zoomIdentity);
<script src="https://unpkg.com/d3@5.15.0/dist/d3.min.js"></script>
    <div id="zoom-chart" class="chart large">
    </div>