为什么d3.scaleLinear域会影响V4中的条形偏移量?

时间:2017-01-24 02:33:00

标签: ruby-on-rails d3.js

我在d3.js中绘制了我的第一个条形图,并且对scaleLinear()对条形位置的影响感到非常惊讶。

首先我将比例定义为:

      var y = d3.scaleLinear()
      .domain([0,100])
      .range([0,300]);

结果如下: chart with domain=100

实际上,域名太大,20就足够了。所以我设置:

      var y = d3.scaleLinear()
      .domain([0,20])
      .range([0,300]);

结果如下: chart with domain=20

条形较长,这是正确的,但它们被推下来,但事实并非如此。以下是嵌入Ruby on Rails 5.0部分的完整脚本。

有人可以解释这种行为并帮我解决问题吗?

非常感谢。

完整的脚本:

  <script>
      // Progression data

     var errors = <%= d3_chart_series_for(this_object).map { |measure| {index: measure.idx, count: measure.score}}.to_json.html_safe   %>;
  // Returns an array of hashes
  //       var errors = [{"index":"2017-01-14","count":"5.35"},{"index":"2017-01-15","count":"2.24"},{"index":"2017-01-16","count":"1.55"},{"index":"2017-01-17","count":"5.11"},{"index":"2017-01-18","count":"2.96"},{"index":"2017-01-19","count":"4.62"},{"index":"2017-01-20","count":"6.71"},{"index":"2017-01-21","count":"9.47"},{"index":"2017-01-22","count":"8.15"},{"index":"2017-01-23","count":"9.25"},{"index":"2017-01-24","count":"5.35"}];

     var x = d3.scaleTime()
      .domain([
          new Date(Date.parse('<%=history_date.strftime("%Y-%m-%d")%>')),
          new Date()
          ])
      .range([0,500]);

      var y = d3.scaleLinear()
      .domain([0,100])
      .range([0,300]);

      var xAxis = d3.axisTop(x)
      .ticks(10);

      var yAxis = d3.axisRight(y)
      .ticks(5);

      var graph =  d3.select('#progression')
      .append('svg')
      .attr('width', 650)
      .attr('height', 400);

      var bars = graph.selectAll('rect')
      .data(errors);

      var newBars = bars.enter();

graph.append('g')
    .attr('class', 'x axis')
    .attr("transform", "translate(100,50)")
    .call(xAxis);

graph.append('g')
    .attr('class', 'y axis')
    .attr("transform", "translate(600,50)")
    .call(yAxis);

newBars.append('rect')
    .attr("transform", "translate(100,0)")
    .attr('x',function(d, i) {
      return x(Date.parse(d.index));})
    .attr('y',y(20))
    .attr('height', function(d,i) {
      return y(d.count);})
    .attr('width', 20 )
    .attr('fill', d3.scale.category20());

  </script>

1 个答案:

答案 0 :(得分:1)

这是问题所在:

.attr('y',y(20))

当您执行此操作以设置条形的y位置时,您未定义固定位置,而是根据域而变化的位置。因此,每次更改域名时,y(20)都会映射到范围内的其他值。

检查一下:

var y = d3.scaleLinear()
    .domain([0, 100])
    .range([50, 300]);

console.log(y(20));//returns 100

var y = d3.scaleLinear()
    .domain([0, 20])
    .range([50, 300]);

console.log(y(20));//returns 300

解决方案:将条形的顶部设置为x轴的相同y位置,在代码中为50:

.attr('y', 50)

如果你想要填充,只需在该值上添加一些东西。

这是一个演示,y域从0到20,如您所要求的那样:

&#13;
&#13;
var errors = [{"index":"2017-01-14","count":"5.35"},{"index":"2017-01-15","count":"2.24"},{"index":"2017-01-16","count":"1.55"},{"index":"2017-01-17","count":"5.11"},{"index":"2017-01-18","count":"2.96"},{"index":"2017-01-19","count":"4.62"},{"index":"2017-01-20","count":"6.71"},{"index":"2017-01-21","count":"9.47"},{"index":"2017-01-22","count":"8.15"},{"index":"2017-01-23","count":"9.25"},{"index":"2017-01-24","count":"5.35"}];

var parse = d3.timeParse("%Y-%m-%d");

errors.forEach(function(d){
d.index = parse(d.index);
});


     var x = d3.scaleTime()
      .domain(d3.extent(errors, function(d){ return d.index}))
      .range([0,500]);
			

      var y = d3.scaleLinear()
      .domain([0,20])
      .range([50,300]);

      var xAxis = d3.axisTop(x)
      .ticks(10);

      var yAxis = d3.axisRight(y)
      .ticks(5);

      var graph =  d3.select('body')
      .append('svg')
      .attr('width', 650)
      .attr('height', 400);

      var bars = graph.selectAll('rect')
      .data(errors);

      var newBars = bars.enter();

graph.append('g')
    .attr('class', 'x axis')
    .attr("transform", "translate(100,50)")
    .call(xAxis);

graph.append('g')
    .attr('class', 'y axis')
    .attr("transform", "translate(600,50)")
    .call(yAxis);

newBars.append('rect')
    .attr("transform", "translate(100,0)")
    .attr('x',function(d) {
      return x(d.index);})
    .attr('y', 50)
    .attr('height', function(d,i) {
      return y(d.count);})
    .attr('width', 20 )
    .attr('fill', "teal");
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
&#13;
&#13;
&#13;

PS :条形图和时间刻度不能很好地混合......你可以看到条纹在精确的日期开始,但它们的宽度使得他们在错误的日期完成。将它们移到左侧,或者更好的选择,使用另一个比例(作为带尺)。