【问题标题】:Transitions with nested data D3.js带有嵌套数据的转换 D3.js
【发布时间】:2017-07-05 20:59:53
【问题描述】:

我最近开始学习 D3.js,我正在努力使用以下数据在散点图中创建过渡:

var data = [
    {"year" : "2004", "x":100, "y":300, "size": 2, "type": "A"},
    {"year" : "2005", "x":200, "y":200, "size": 2, "type": "A"},
    {"year" : "2006", "x":300, "y":100, "size": 2, "type": "A"},
    {"year" : "2004", "x":150, "y":250, "size": 2.382450, "type": "B"},
    {"year" : "2005", "x":150, "y":250, "size": 3.078548, "type": "B"},
    {"year" : "2006", "x":150, "y":250, "size": 4.265410, "type": "B"}];

在散点图中有 2 个点(类型 A&B),它们的位置 (x&y) 和大小每年都会发生变化。我创建了一个fiddle,我尝试在其中嵌套数据并绘制点,但是使用transition() 函数的下一步令人困惑。更具体地说,我仍在声明整个数据,但要使转换工作,我只需要部分数据。

【问题讨论】:

  • 我不完全确定您需要什么,但我认为您需要按类型嵌套,并为每种类型创建圆圈。但是您需要一些东西来触发转换(用户点击、计时器?)以迭代每年的 data.values。
  • 如果两种类型的圆圈同时出现在屏幕上,过渡应该如何工作。

标签: d3.js


【解决方案1】:

了解你想要什么的关键在这里:

有 2 个点,它们每年都会改变位置 (x&y) 和大小

因此,这显然是XY problem。您的问题不是“如何使用嵌套数据进行转换”。你的问题是“如何按年过渡”

我提出的解决方案首先涉及删除嵌套数组。你不需要那个。

相反,获取数据中的所有年份...

var years = [...new Set(data.map(function(d) {
  return d.year
}))];

...,按年份过滤数据...

var dataStart = data.filter(function(d) {
  return d.year === years[0]
});

... 并循环多年。在这里,我使用的是d3.interval()

var counter = 1;
var timer = d3.interval(transition, 1500);

function transition() {

  var newData = data.filter(function(d) {
    return d.year === years[counter]
  });

  svg.selectAll("circle").data(newData)
    .transition()
    .duration(1000)
    .attr("cx", function(d) {
      console.log(d)
      return d.x;
    })
    .attr("cy", function(d) {
      return d.y;
    })
    .attr("r", function(d) {
      return d.size * 10;
    });
  counter += 1;
  if (counter === 3) {
    timer.stop()
  }
}

这里是演示:

var data = [{
      "year": "2004",
      "x": 100,
      "y": 100,
      "size": 2,
      "type": "A"
    }, {
      "year": "2005",
      "x": 200,
      "y": 180,
      "size": 2,
      "type": "A"
    }, {
      "year": "2006",
      "x": 300,
      "y": 50,
      "size": 2,
      "type": "A"
    }, {
      "year": "2004",
      "x": 150,
      "y": 150,
      "size": 2.382450,
      "type": "B"
    }, {
      "year": "2005",
      "x": 150,
      "y": 50,
      "size": 3.078548,
      "type": "B"
    }, {
      "year": "2006",
      "x": 150,
      "y": 100,
      "size": 4.265410,
      "type": "B"
    }];

    var width = 400,
      height = 200;

    var svg = d3.select("body").append("svg")
      .attr("width", width)
      .attr("height", height);

    var years = [...new Set(data.map(function(d) {
      return d.year
    }))];

    var dataStart = data.filter(function(d) {
      return d.year === years[0]
    });

    var cell = svg.selectAll("circle")
      .data(dataStart);

    cell.enter()
      .append("circle")
      .attr("cx", function(d) {
        return d.x;
      })
      .attr("cy", function(d) {
        return d.y;
      })
      .attr("r", function(d) {
        return d.size * 10;
      });

    var counter = 1;
    var timer = d3.interval(transition, 1500);

    function transition() {

      var newData = data.filter(function(d) {
        return d.year === years[counter]
      });

      svg.selectAll("circle").data(newData)
        .transition()
        .duration(1000)
        .attr("cx", function(d) {
          return d.x;
        })
        .attr("cy", function(d) {
          return d.y;
        })
        .attr("r", function(d) {
          return d.size * 10;
        });
      counter += 1;
      if (counter === 3) {
        timer.stop()
      }
    }
<script src="https://d3js.org/d3.v4.min.js"></script>

【讨论】:

  • 谢谢,这确实达到了我的期望。我试图避免循环,因为我读到你可以使用 D3.js 使用嵌套来避免循环,但我想循环在这里很好
  • 确实,在添加元素时,您应该始终避免在 D3 中出现循环。但在这里你说的是改变数据,这是不同的。
猜你喜欢
  • 2015-10-17
  • 1970-01-01
  • 2011-10-30
  • 1970-01-01
  • 2016-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-09
相关资源
最近更新 更多