【问题标题】:In D3 bar graph, y-axis ordinal scale is not aligning properly with bars在 D3 条形图中,y 轴序数比例未与条正确对齐
【发布时间】:2016-07-13 16:52:51
【问题描述】:

我正在关注Mike's tutorial Let's make a bar graph part IIpart III 以获取 d3 中的条形图。
我最终得到一个水平条形图。
问题是我无法将 y 轴标签设置为与其各自的条对齐,也许我的序数比例或设置条的 y 位置有问题。
此外,图表栏从顶部而不是基线开始。

	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;
}
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"&gt;&lt;/script&gt;

【问题讨论】:

    标签: javascript d3.js graph


    【解决方案1】:

    问题一:

    而不是这个:

      var _barThickness = 20;
    

    这样做:

      var _barThickness = scales.y.rangeBand();
    

    阅读here

    如果你想调节厚度

    而不是这个:

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

    这样做:

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

    问题 2:

    变换不正确。

    而不是这个:

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

    这样做:

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

    问题 3:

    条形图的 y 计算不正确。

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

    这样做:

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

    工作代码here

    【讨论】:

    • 谢谢,它工作正常,但是当我更新条形图中的数据时,接下来的事情不是更新值,而是在前一个上重绘图表。这是更新的小提琴链接jsfiddle.net/ankibalyan/hr3rrjtp,当您单击栏时,它应该更新其子数据。
    • 我相信这是关于 SO 的另一个问题。
    猜你喜欢
    • 2015-06-25
    • 2017-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多