简体   繁体   中英

In D3 bar graph, y-axis ordinal scale is not aligning properly with bars

I was following Mike's tutorial Let's make a bar graph part II , part III for the bar graph in d3.
I end up with a horizontal bar graph.
The Problem is I'm not able to set the y-axis labels aligned with its respective bar, maybe I'm somewhere wrong with ordinal scale or setting up the y position of the bars.
Also, the graph bars are starting from the top instead of baseline.

  var options = { margin: { top: 0, right: 30, bottom: 0, left: 50 }, width: 560, height: 400, element: 'body', colors: ["#f44336", "#e91e63", "#673ab7", "#3f51b5", "#2196f3", "#03a9f4", "#00bcd4", "#009688", "#4caf50", "#8bc34a", "#cddc39", "#ffeb3b", "#ffc107", "#ff9800", "#ff5722", "#795548", "#607d8b"] }; options.mWidth = options.width - options.margin.left - options.margin.right; options.mHeight = options.height - options.margin.top - options.margin.bottom; var _colorScale = d3.scale.ordinal() // .domain([minValue,maxValue]) .range(options.colors); var items = Math.round((Math.random() * 10) + 3); var data = []; for (var i = 0; i < items; i++) { data.push({ label: 'label' + i, value: Math.random() * 100 }); } var _barThickness = 20; var width = options.mWidth, height = options.mHeight; var svg = d3.select(options.element) .append("svg") .attr("width", width).attr("height", height) .attr("viewBox", "0 0 " + options.width + " " + options.height) //.attr("preserveAspectRatio", "xMinYMin meet") .append("g"); svg.attr("transform", "translate(" + options.margin.left * 2 + "," + options.margin.top + ")"); var maxValue = 0, minValue = 0; for (var i = 0; i < data.length; i++) { maxValue = Math.max(maxValue, data[i].value); minValue = Math.min(minValue, data[i].value); } var scales = { x: d3.scale.linear().domain([0, maxValue]).range([0, width / 2]), y: d3.scale.ordinal().rangeRoundBands([0, height], .1) } scales.y.domain(data.map(function(d) { return d.label; })); var bars = svg.append("g") .attr("class", "bar"); var xAxis = d3.svg.axis() .scale(scales.x) .orient("bottom") .ticks(5); var yAxis = d3.svg.axis() .scale(scales.y) .orient("left"); var xaxis = svg.append("g") .attr("class", "x axis") .attr('transform', 'translate(' + 0 + ',' + height + ')') .call(xAxis) .append("text") .attr("x", width / 2) .attr("dy", "3em") .style("text-anchor", "middle") .text("Durations in hours"); var yaxis = svg.append("g") .attr("class", "y axis") .attr('transform', 'translate(' + 0 + ',' + 0 + ')') .call(yAxis) .append("text") .attr("transform", "rotate(-90)") .attr("y", -options.margin.left) .attr("x", -height / 2) .attr("dy", ".71em") .style("text-anchor", "middle") .text("Labels"); var bar = bars.selectAll('rect.bar').data(data); var rect = bar.enter() .append('g') .attr('transform', function(d, i) { return 'translate(0,' + parseInt(i * _barThickness + 2) + ')'; }); rect.append('rect') .attr('class', 'bar') .attr('fill', function(d) { return _colorScale(d.value); }) .attr('width', function(d) { return scales.x(d.value); }) .attr('height', _barThickness - 1) .attr('y', function(d, i) { return (i * _barThickness); }) rect.append('text') .attr('x', function(d) { return scales.x(d.value) + 2; }) .attr('y', function(d, i) { return (i * _barThickness); }) .attr('dy', '0.35em') .text(function(d) { return Math.round(d.value); }); 
 svg { width: 100%; height: 100%; } text { font-size: 0.8em; line-height: 1em; } path.slice { stroke-width: 2px; } polyline { opacity: .3; stroke: black; stroke-width: 2px; fill: none; } .axis { font: 10px sans-serif; } .axis path, .axis line { fill: none; stroke: #000; shape-rendering: crispEdges; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script> 

Problem 1:

Instead of this:

  var _barThickness = 20;

Do this:

  var _barThickness = scales.y.rangeBand();

Read here

If you want to regulate the thickness

Instead of this:

y: d3.scale.ordinal().rangeRoundBands([0, height], .1)

Do this:

y: d3.scale.ordinal().rangeRoundBands([0, height], .7)

Problem 2:

Incorrect transform.

Instead of this:

var rect = bar.enter()
  .append('g')
  .attr('transform', function(d, i) {
    return 'translate(0,' + parseInt(i * _barThickness + 2) + ')';
  });

Do this:

var rect = bar.enter()
  .append('g');

Problem 3:

Incorrect calculation of y for the bars.

  .attr('y', function(d, i) {
    return (i * _barThickness);
  })

Do this:

  .attr('y', function(d, i) {
    return scales.y(d.label);
  })

working code here

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