javascript - 调整窗口大小时的 d3 缩放行为

标签 javascript d3.js

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

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

问题发生在窗口大小调整上。在执行以下步骤后,我注意到缩放焦点不再与鼠标对齐:

  • 首先平移和放大图表区域
  • 然后调整窗口大小
  • 然后再次平移和缩放图表区域

  • 之后,就出现了上面的问题。请参阅以下有此问题的 jsfiddle。

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

    d3 Preserve scale/translate after resetting range

    我尝试了这种方法,但我无法使用 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>

    关于javascript - 调整窗口大小时的 d3 缩放行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39735367/

    相关文章:

    javascript - Angular 上传 - 发送 FormData 时出现错误 405

    JavaScript 替换电子邮件地址

    html - 在 d3 中选择深层元素

    javascript - D3 更新共现图中的颜色

    javascript - 导入文件需要时间,代码失败后出现

    javascript - 全局对象是哪个类的对象?

    javascript - D3更新画笔的比例不更新画笔

    javascript - D3 桑基图上的颜色特定链接

    javascript - 无需加载页面即可交换内部图库和 HTML

    javascript - NVD3.js 中的 .datum 多个值