可排序条形图不起作用

时间:2018-03-10 04:02:52

标签: javascript d3.js

刚开始学习D3所以这应该是一个基本的修复。无论如何,我试图通过点击进行简单的条形图排序。经过几个小时的搜索,似乎无法弄明白。

我的猜测是它与过渡或音阶有关,但我当然是新手。

这是代码。



<script src="https://d3js.org/d3.v4.min.js"></script>

<body>
  <script>
    var w = 600;
    var h = 250;

    var dataset = [{
        "namePlayer": "Player1",
        "mean": 37.4375
      },
      {
        "namePlayer": "Player2",
        "mean": 13.6937
      },
      {
        "namePlayer": "Player3",
        "mean": 26.7
      },
      {
        "namePlayer": "Player5",
        "mean": 20.0804
      },
      {
        "namePlayer": "Player6",
        "mean": 27.9235
      }
    ];

    var xScale = d3.scaleBand()
      .domain(dataset.map(function(d, i) {
        return d.namePlayer;
      }))
      .range([w, 0])
      .padding(0.05);
    var yScale = d3.scaleLinear()
      .domain([0, d3.max(dataset, function(d) {
        return d.mean;
      })])
      .range([h, 0]);
    var svg = d3.select("body")
      .append("svg")
      .attr("width", w)
      .attr("height", h);

    var xAxis = d3.axisBottom()
      .scale(xScale);



    svg.selectAll("rect")
      .data(dataset)
      .enter()
      .append("rect")
      .attr("x", function(d) {
        return xScale(d.namePlayer);
      })
      .attr("width", xScale.bandwidth())
      .attr("y", function(d) {
        return yScale(d.mean);
      })
      .attr("height", function(d) {
        return h - yScale(d.mean);
      })
      .attr("fill", function(d) {
        return "rgb(0, 0, " + Math.round(d.mean * 10) + ")";
      })
      .on("click", function() {
        sortBars();
      })

    var sortBars = function() {
      svg.selectAll("rect")
        .sort(function(a, b) {
          return d3.ascending(a.mean, b.mean);
        })
        .transition()
        .delay(function(d) {
          return d.mean * 50;
        })
        .duration(1000)
        .attr("x", function(d) {
          return xScale(d.mean);
        });
    };
  </script>
</body>
&#13;
&#13;
&#13;

感谢帮助!

1 个答案:

答案 0 :(得分:1)

现在您只需对选择进行排序(并将错误的属性传递给xScale比例)。

而不是那样,你应该对数据进行排序......

dataset.sort(function(a, b) {
    return d3.ascending(a.mean, b.mean);
});

...并将其传递给xScale

xScale.domain(dataset.map(function(d, i) {
    return d.namePlayer;
}));

然后,您可以使用转换。

以下是更新后的代码:

&#13;
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>

<body>
  <script>
    var w = 600;
    var h = 250;

    var dataset = [{
        "namePlayer": "Player1",
        "mean": 37.4375
      },
      {
        "namePlayer": "Player2",
        "mean": 13.6937
      },
      {
        "namePlayer": "Player3",
        "mean": 26.7
      },
      {
        "namePlayer": "Player5",
        "mean": 20.0804
      },
      {
        "namePlayer": "Player6",
        "mean": 27.9235
      }
    ];

    var xScale = d3.scaleBand()
      .domain(dataset.map(function(d, i) {
        return d.namePlayer;
      }))
      .range([w, 0])
      .padding(0.05);
    var yScale = d3.scaleLinear()
      .domain([0, d3.max(dataset, function(d) {
        return d.mean;
      })])
      .range([h, 0]);
    var svg = d3.select("body")
      .append("svg")
      .attr("width", w)
      .attr("height", h);

    var xAxis = d3.axisBottom()
      .scale(xScale);

    svg.selectAll("rect")
      .data(dataset)
      .enter()
      .append("rect")
      .attr("x", function(d) {
        return xScale(d.namePlayer);
      })
      .attr("width", xScale.bandwidth())
      .attr("y", function(d) {
        return yScale(d.mean);
      })
      .attr("height", function(d) {
        return h - yScale(d.mean);
      })
      .attr("fill", function(d) {
        return "rgb(0, 0, " + Math.round(d.mean * 10) + ")";
      })
      .on("click", function() {
        sortBars();
      })

    var sortBars = function() {
      dataset.sort(function(a, b) {
        return d3.ascending(a.mean, b.mean);
      });
      xScale.domain(dataset.map(function(d, i) {
        return d.namePlayer;
      }));
      svg.selectAll("rect")
        .transition()
        .delay(function(d) {
          return d.mean * 50;
        })
        .duration(1000)
        .attr("x", function(d) {
          return xScale(d.namePlayer);
        });
    };

  </script>
</body>
&#13;
&#13;
&#13;