简体   繁体   中英

d3.js bar graph is not showing bars

I read previously answered questions but had no luck. I am plotting a bar graph of elements on array using d3.js but the bars are not shown as they should be. This is the script I am trying:

 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> 

I do feel that the problem is in last few lines, fetching x, y, width and height. I can't understand what values to return, I tried various, but didn't get the graph. So, I have just put return 0 there. What should be the values? And how to decide it? Thank you for help. :)

Your scaleBand().domain() has to be an array for the Xscale . In my solution I choose to have the indexes of the values as the array. You could map your data (usually an array of objects) to other values of the objects in an array. Additionally there were several other issues with the scaling in terms of height and width of the actual bars and their positioning. Keep in mind that the SVG origin is the top left corner and everything is with respect to that.

I have updated the code below which makes necessary changes to produce a bar graph. Please go through it and let me know if there is anything that you do not understand.

 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> 

I recommand you to read this article. It explain very well how to use bar charts. https://blog.risingstack.com/d3-js-tutorial-bar-charts-with-javascript/

I used your code and did a simple example. https://codepen.io/mp-9007/pen/jJpEWY

The main issues are because of the return values of x, y and height; You have to provide the x and y position in the graph area. Drawing the bar chart is like drawing on a Cartesian plane, you must provide the coordinate of where to start the bar, the width of the bar and the height of it. The origin of the plan is at the top left of the image.

.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.
});

Also, the domain for the x-axis can be think as categories. In your code, you were providing only two category: 0 and data.length . Provinding the array solved this issue.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM