d3v4 - 缩放(相当于 d3.zoom.x)

Posted

技术标签:

【中文标题】d3v4 - 缩放(相当于 d3.zoom.x)【英文标题】:d3v4 - zooming (Equivalent to d3.zoom.x) 【发布时间】:2017-01-16 04:43:36 【问题描述】:

我正在将我的 d3 代码从 v3 迁移到 v4,但在查找 d3.zoom.x、d3.zoom.y 属性的等效项时遇到问题。

下面是一小段代码,包括最重要的元素:

            this.init = function(obj, def) 

            /* X-axis */
            x = d3.scaleTime()
                .range([0, width]);


            xAxis = d3.axisBottom(x)
                .ticks(ticks);

            svg.append("g")
                .attr("class", "x axis")
                .attr("transform", "translate(0," + height + ")");

            /* Y-axis */
            for (var i = 0; i < 1; i++) 
                // Returns the y and yAxis as arrays
                createYAxis(i);
            

            initZoom();

        ;
            // Zoom trigger
            var drawUpdXY = function()
                setPause(true);
                drawUpd();
                zoomY.y(y[0]);
                zoomX.x(x);


            zoom = d3.zoom()
                .on("zoom", drawUpdXY);

            zoomX = d3.zoom()
                .on("zoom", drawUpdX);

            zoomY = d3.zoom()
                .on("zoom", drawUpdY);
            ;     

我尝试用它来替换“zoom.x(x); zoom.y(y[0])”

      xAxis.scale(d3.event.transform.rescaleX(x));
      yAxis[0].scale(d3.event.transform.rescaleY(y[0]));

但是,这些只会重新缩放轴,而不会缩放数据。

【问题讨论】:

既然这个比较老了,你有没有找到解决办法?我遇到了同样的问题。 今天还没有找到解决方案 - 我决定等到有更大的 v4 社区。​​span> tl;dr:这可能有助于重组你的重构,查看链接了解原因和方式,以及它的工作示例 b> 我正在做一个类似的项目,试图在 d3v4 和 React 中实现平移/缩放坐标网格系统。在此过程中,我使用了article explaining how the new zooming/panning works,这让我意识到我必须重新考虑如何构建我的重构。然后,我在纯 d3 中创建了这个 codepen of what I was trying to make。仍在 React 方面工作。 【参考方案1】:

我无法谈论 d3 v3 是如何处理缩放的,因为我最近才开始使用 D3,但下面的代码应该可以让您找到正确的方向。我会尽力描述发生了什么。我邀请更正、改进和更好的解释。

首先,MCVE

<html>

<head>
  <meta charset="UTF-8">
  <title>Energy Visualizer</title>
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <script src="https://d3js.org/d3-color.v1.min.js"></script>
  <script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
  <script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
  <style>
    body 
      background-color: #4e5965;
    
  </style>
  </svg>
</head>

<body>
  <div class="chart" />
  <script>
    var svg = d3.select(".chart").append("svg")
      .attr("width", 200)
      .attr("height", 200);

    var data = [
      "x": 2,
      "y": 8,
      "color": "green"
    , 
      "x": 4,
      "y": 6,
      "color": "red"
    ];

    var width = svg.attr("width");
    var height = svg.attr("height");

    x_scale = d3.scaleLinear().domain([0, 10]).range([0, width]);
    y_scale = d3.scaleLinear().domain([0, 10]).range([0, height]);

    var circles = svg.selectAll("circle")
      .data(data)
      .enter()
      .append("circle")
      .attr("cx", function(d) 
        return x_scale(d.x);
      )
      .attr("cy", function(d) 
        return y_scale(d.y);
      )
      .attr("r", 5)
      .attr("fill", function(d) 
        return d.color
      );

    var xAxis = d3.axisBottom(x_scale);
    var yAxis = d3.axisRight(y_scale);

    var x_axis = svg.append("g").call(xAxis);
    var y_axis = svg.append("g").call(yAxis);
  </script>
</body>

</html>

这只是一个带有红色和绿色圆圈的简单散点图。您可以看到我是如何分解 x 和 y 轴的组件的。这与d3.zoom() 一起发挥作用。

接下来,让我们添加一个缩放组件。

<html>

<head>
  <meta charset="UTF-8">
  <title>Energy Visualizer</title>
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <script src="https://d3js.org/d3-color.v1.min.js"></script>
  <script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
  <script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
  <style>
    body 
      background-color: #4e5965;
    
  </style>
  </svg>
</head>

<body>
  <div class="chart" />
  <script>
    var svg = d3.select(".chart").append("svg")
      .attr("width", 200)
      .attr("height", 200);

    var zoom = d3.zoom()
      .on("zoom", zoomed);

    svg.call(zoom);

    var data = [
      "x": 2,
      "y": 8,
      "color": "green"
    , 
      "x": 4,
      "y": 6,
      "color": "red"
    ];

    var width = svg.attr("width");
    var height = svg.attr("height");

    x_scale = d3.scaleLinear().domain([0, 10]).range([0, width]);
    y_scale = d3.scaleLinear().domain([0, 10]).range([0, height]);

    var circles = svg.selectAll("circle")
      .data(data)
      .enter()
      .append("circle")
      .attr("cx", function(d) 
        return x_scale(d.x);
      )
      .attr("cy", function(d) 
        return y_scale(d.y);
      )
      .attr("r", 5)
      .attr("fill", function(d) 
        return d.color
      );

    var xAxis = d3.axisBottom(x_scale);
    var yAxis = d3.axisRight(y_scale);

    var x_axis = svg.append("g").call(xAxis);
    var y_axis = svg.append("g").call(yAxis);


    function zoomed() 
      var new_x_scale = d3.event.transform.rescaleX(x_scale);
      var new_y_scale = d3.event.transform.rescaleY(y_scale);

      x_axis.transition()
        .duration(0)
        .call(xAxis.scale(new_x_scale));

      y_axis.transition()
        .duration(0)
        .call(yAxis.scale(new_y_scale));

      circles
        .attr("cx", function(d) 
          return new_x_scale(d.x)
        )
        .attr("cy", function(d) 
          return new_y_scale(d.y)
        );

    
  </script>
</body>

</html>

在这里,您可以看到图表允许在两个轴上放大、缩小和拖动。我相信你只想要一个单轴缩放,所以在这种情况下,只需要重新缩放 x 轴和每个圆圈位置的 x 分量。

最后一个 sn-p 做我认为你想做的事。

<html>

<head>
  <meta charset="UTF-8">
  <title>Energy Visualizer</title>
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <script src="https://d3js.org/d3-color.v1.min.js"></script>
  <script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
  <script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
  <style>
    body 
      background-color: #4e5965;
    
  </style>
  </svg>
</head>

<body>
  <div class="chart" />
  <script>
    var svg = d3.select(".chart").append("svg")
      .attr("width", 200)
      .attr("height", 200);

    var zoom = d3.zoom()
      .on("zoom", zoomed);

    svg.call(zoom);

    var data = [
      "x": 2,
      "y": 8,
      "color": "green"
    , 
      "x": 4,
      "y": 6,
      "color": "red"
    ];

    var width = svg.attr("width");
    var height = svg.attr("height");

    x_scale = d3.scaleLinear().domain([0, 10]).range([0, width]);
    y_scale = d3.scaleLinear().domain([0, 10]).range([0, height]);

    var circles = svg.selectAll("circle")
      .data(data)
      .enter()
      .append("circle")
      .attr("cx", function(d) 
        return x_scale(d.x);
      )
      .attr("cy", function(d) 
        return y_scale(d.y);
      )
      .attr("r", 5)
      .attr("fill", function(d) 
        return d.color
      );

    var xAxis = d3.axisBottom(x_scale);
    var yAxis = d3.axisRight(y_scale);

    var x_axis = svg.append("g").call(xAxis);
    var y_axis = svg.append("g").call(yAxis);


    function zoomed() 
      var new_x_scale = d3.event.transform.rescaleX(x_scale);

      x_axis.transition()
        .duration(0)
        .call(xAxis.scale(new_x_scale));

      circles
        .attr("cx", function(d) 
          return new_x_scale(d.x)
        );

    
  </script>
</body>

</html>

【讨论】:

以上是关于d3v4 - 缩放(相当于 d3.zoom.x)的主要内容,如果未能解决你的问题,请参考以下文章

GCP 托管实例组不会缩放到零

在 D3 中放大和缩小时如何更改平移和缩放的速度(使用 zoom.on 和 d3.event.translate,d3.event.zoom)?

D3 V4 缩放以使用流式投影在画布中显示

在放大和缩小时在imageview上移动对象

缩放 d3 v4 地图以适合 SVG(或根本不适合)

缩放 d3 v4 地图以适合 SVG(或根本不适合)