【问题标题】:d3.js bar graph is not showing barsd3.js 条形图不显示条形
【发布时间】:2019-03-18 16:05:08
【问题描述】:

我阅读了以前回答的问题,但没有运气。 我正在使用 d3.js 在数组上绘制元素的条形图,但条形图未按应有的方式显示。 这是我正在尝试的脚本:

var data = [1, 2, 3, 4, 5];
var svg = d3.select("svg");
var margin = 100,
  width = svg.attr("width") - margin,
  height = svg.attr("height") - margin;
var Xscale = d3.scaleBand()
  .domain([0, data.length])
  .range([0, width])
  .padding(0.2);
var Yscale = d3.scaleLinear()
  .domain([0, d3.max(data)])
  .range([height, 0]);
var g = svg.append("g")
  .attr("transform", "translate(" + 100 + "," + 100 + ")");
g.append("g")
  .attr("transform", "translate(0," + height + ")")
  .call(d3.axisBottom(Xscale).tickFormat(function(d) {
    return d;
  }).ticks(10));
// .append("text")
// .attr("x", 6)
// .attr("text-anchor", "end")
// .text("index");

g.append("g")
  .call(d3.axisLeft(Yscale).tickFormat(function(d) {
    return d;
  }).ticks(10))
  .append("text")
  .attr("y", 6)
  .attr("dy", "0.71em")
  .attr("text-anchor", "end")
  .text("value");


g.selectAll(".bar")
  .data(data)
  .enter().append("rect")
  .attr("class", "bar")
  .attr("x", function(d, i) {
    return 0;
  })
  .attr("y", function(d, i) {
    return 0;
  })
  .attr("width", Xscale.bandwidth())
  .attr("height", function(d, i) {
    return 0;
  });
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <title>Bar chart with D3.js</title>

  <link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
  <link rel="stylesheet" type="text/css" href="styles/da.css">
  <script src="https://d3js.org/d3.v5.min.js"></script>

  <!-- <script src="js/da.js"></script> -->
</head>

<body>
  <div id='layout'>
    <h2>Bar chart example</h2>
    <div class='container'>
      <svg class="chart" height="500" width="1000" />
    </div>
  </div>
  <p>Why this is not working?? </p>
</body>

</html>

我确实觉得问题出在最后几行,获取 x、y、宽度和高度。我不明白要返回什么值,我尝试了各种,但没有得到图表。所以,我刚刚把 return 0 放在那里。 价值观应该是什么?以及如何决定? 谢谢你的帮助。 :)

【问题讨论】:

  • da.css 中有什么?也许缺少 CSS?

标签: javascript d3.js


【解决方案1】:

您的scaleBand().domain() 必须是Xscale 的数组。在我的解决方案中,我选择将值的索引作为数组。您可以将数据(通常是对象数组)映射到数组中对象的其他值。 此外,在实际条形的高度和宽度及其位置方面,缩放还存在其他几个问题。请记住,SVG 原点位于左上角,一切都与此相关。

我更新了下面的代码,对生成条形图进行了必要的更改。请仔细阅读,如果有什么不明白的地方请告诉我。

var data = [1, 2, 3, 4, 5];
var svg = d3.select("svg");
var margin = 100,
  width = svg.attr("width") - margin,
  height = svg.attr("height") - margin;
var Xscale = d3.scaleBand()
  .domain(data.map((e,i) => i)) //returns array [0,1,2,3,4] for the index of the values
  .range([0, width])
  .padding(0.2);
var dmax = d3.max(data) //calculates the max value of the data
var Yscale = d3.scaleLinear()
  .domain([0, dmax])
  .range([height, 0]);
  
var g = svg.append("g")
  .attr("transform", "translate(" + 50 + "," + 50 + ")");

var x = g.append("g")
  .attr("transform", "translate(0," + height + ")")
  .call(d3.axisBottom(Xscale).tickFormat(function(d) {
    return d;
  }).ticks(10))
 .append("text")
 .attr("x", 6)
 .attr("text-anchor", "end")
 .text("index");

var y = g.append("g")
  .call(d3.axisLeft(Yscale).tickFormat(function(d) {
    return d;
  }).ticks(10))
  .append("text")
  .attr("y", 6)
  .attr("dy", "0.71em")
  .attr("text-anchor", "end")
  .text("value");

g.selectAll(".bar")
  .data(data)
  .enter().append("rect")
  .attr("class", "bar")
  .attr("x", function(d, i){ return Xscale(i)}) //move the bar to the x position where it should appear
  .attr("y", function(d, i) { return Yscale(d); }) //move the bar from the top down to the level of the value.
  .attr("width", Xscale.bandwidth() ) //the width of the bar is the width between the points on the x-axis 
  .attr("height", function(d, i) {
    return Yscale(dmax-d);
  }); // the height of the points is calculated based on the scale and the difference between this point and the max value of the data.
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <title>Bar chart with D3.js</title>
  <link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
  <script src="https://d3js.org/d3.v5.min.js"></script>

</head>

<body>
  <div id='layout'>
    <h2>Bar chart example</h2>
    <div class='container'>
      <svg class="chart" height="500" width="1000" />
    </div>
  </div>
  <p>Why this is not working?? </p>
</body>

</html>

【讨论】:

  • 非常感谢,它成功了。我无法将两个答案标记为正确,但你的答案也很好。
  • 接受的答案会遇到麻烦,因为 x 轴标签将取决于值,这不是标记轴的正确方法。例如,如果您的data = [500, 20, 1, 20, 300] 它将停止工作,因为值 20 出现了 2 次,并且无法映射该条的 x 坐标。我提供的答案更好,因为它使用值的索引来映射 x 轴上的域。您也可以将 .domain(data.map((e,i) =&gt; i+1)).attr("x", function(d, i){ return Xscale(i+1)}) 更改为从 x 轴上的 1 而不是 0 开始。
  • 哦,我刚注意到这一点。谢谢。将此标记为答案。我也想问怎么暂停画一段时间?我的意思是我想为数组绘制条形图,显示 2 秒,然后更改数组,显示新数组。请帮助:} 我知道的方法 setTimeout 不起作用
  • 嗨尼基尔。要更新数据,您必须查看 github.com/d3/d3-selection/blob/master/README.md#selection_join 和转换 github.com/d3/d3-transition 。这是一篇讨论进入退出更新medium.com/@c_behrens/enter-update-exit-6cafc6014c36的文章
【解决方案2】:

我建议您阅读这篇文章。它很好地解释了如何使用条形图。 https://blog.risingstack.com/d3-js-tutorial-bar-charts-with-javascript/

我使用了您的代码并做了一个简单的示例。 https://codepen.io/mp-9007/pen/jJpEWY

主要问题是因为 x、y 和 height 的返回值; 您必须在图形区域中提供 x 和 y 位置。绘制条形图就像在笛卡尔平面上绘制一样,您必须提供条形开始位置的坐标、条形的宽度和高度。计划的原点位于图像的左上角。

.attr("x", function(d, i) { //d = input data, i = index of it
    return Xscale(d); //The scaling function returns the coordinate for a given domain value.
})
.attr("y", function(d, i) { //d = input data, i = index of it
    return Yscale(d); //The scaling function returns the coordinate for a given domain value.
})
.attr("width", Xscale.bandwidth())
.attr("height", function(d, i) { //d = input data, i = index of it
    return height - Yscale(d); //The computed y coordinate has to be subtracted from the height of the chart to get the correct representation of the value as a column.
});

此外,x 轴的域可以视为类别。在您的代码中,您只提供了两个类别: 0 和 data.length 。提供数组解决了这个问题。

var Xscale = d3.scaleBand().domain(data)

【讨论】:

  • 谢谢您,先生/女士。它工作得很好。我想问的另一件事是,如果我使用某个函数更改数组,并再次绘制 svg,它会显示新的数组数据吗?我需要删除 svg 并制作新的吗?
  • 这个答案会遇到麻烦。例如,如果您的 data = [500, 20, 1, 20, 300] 它将停止工作,因为值 20 出现了 2 次,并且无法映射该条的 x 坐标。直接使用数值数据来映射域是不明智的。请在下面查看我的答案。
  • 同意你@Coola。不想更改问题的值,也没有考虑将data.map((e,i) =&gt; i) 用于域。感谢您的提示:)
猜你喜欢
  • 1970-01-01
  • 2015-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-04
  • 1970-01-01
相关资源
最近更新 更多