d3v4 - масштабирование (эквивалент d3.zoom.x)

Я переношу свой код 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]));

Однако они только изменяют масштаб оси, оставляя данные без увеличения.

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 каждой позиции окружности.

Последний фрагмент делает то, что я думаю, что вы хотите.

<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>

Другие вопросы по тегам