D3.JS Y轴标签问题

时间:2017-11-13 22:35:57

标签: javascript html css d3.js svg

首先,我是D3.Js的新手。我花了大约一个星期左右的时间研究D3.JS问题 - 专门制作一个带有Y轴标签的图表。但是,我无法准确地获得图表。它几乎就在那里但反转或我的数据出错了。现在,在显示所有代码之前,我将简要展示一些我的主要问题的代码和图像。我花时间查看其他类似问题的Stack Overflow帖子,我在那些帖子上做了什么,但仍然有同样的问题。

例如,我认为这篇文章会有解决方案:reversed Y-axis D3

数据如下:

[0,20,3,8](它实际上是一个对象数组,但我认为这可能是所有需要的。

所以,首先,当yScale是这样的时候:

  var yScale = d3.scaleLinear() 
             .domain([0, maxPound]) //Value of maxpound is 20
             .range([0, 350]);

条形图如下所示: Figure  1

正如人们可以看到Y图表从顶部的零开始,底部的20开始 - 我起初认为这是一个简单的修复,可以将域中的值翻转到此处:

     var yScale = d3.scaleLinear() 
             .domain([0, maxPound]) //Value of maxpound is 20
             .range([0, 350]);

我得到这张图片:

enter image description here

在第二张图片中,y轴是右边的20位于顶部!但这些图表是错误的。 0现在返回350像素的值 - SVG元素的高度。这是20应该返回的价值!如果我尝试切换图像范围值,我会遇到同样的问题!

现在代码:

  var w = 350;
  var h = 350;
  var barPadding = 1;
  var margin = {top: 5, right: 200, bottom: 70, left: 25}

  var maxPound = d3.max(poundDataArray, 
     function(d) {return parseInt(d.Pounds)}
  );

  //Y-Axis Code
  var yScale = d3.scaleLinear()
                 .domain([maxPound, 0])
                 .range([0, h]);

  var yAxis = d3.axisLeft()
                .scale(yScale)
                .ticks(5);


  //Creating SVG element 
  var svg = d3.select(".pounds")
              .append('svg')
              .attr("width", w)
              .attr('height', h)
              .append("g")
                 .attr("transform", "translate(" + margin.left + "," + 
     margin.top + ")");

    svg.selectAll("rect")
       .data(poundDataArray)
       .enter()
       .append("rect")
       .attr('x',  function(d, i){
            return i * (w / poundDataArray.length);
         })
       .attr('y', function(d) {
            return 350 - yScale(d.Pounds);
        })
       .attr('width', (w / 4) - 25)
       .attr('height', function(d){
           return yScale(d.Pounds);
        })
       .attr('fill', 'steelblue');



   //Create Y axis
   svg.append("g")
      .attr("class", "axis")
      .call(yAxis);

感谢您的帮助!我相信错误可能在y或高度值,并花时间在那里乱搞没有结果。

1 个答案:

答案 0 :(得分:2)

这不是D3问题,而是SVG功能:在SVG中,原点(0,0)位于左上角角落,而不是左下角,如同常见的笛卡儿平面。这就是为什么使用[0, h]作为范围会使轴看起来倒置 ...实际上,它没有被反转:这是SVG中正确的方向。顺便说一句,HTML5 Canvas具有相同的坐标系统,使用画布你会遇到同样的问题。

因此,您必须翻转范围,而不是域名

var yScale = d3.scaleLinear()
    .domain([0, maxPound])
    .range([h, 0]);//the range goes from the bottom to the top now

或者,在您的情况下,使用边距:

var yScale = d3.scaleLinear()
    .domain([0, maxPound])
    .range([h - margin.bottom, margin.top]);

除此之外,y位置和高度的数学运算是错误的。它应该是:

.attr('y', function(d) {
    return yScale(d.Pounds);
})
.attr('height', function(d) {
    return h - margin.bottom - yScale(d.Pounds);
})

另外,作为奖励提示,请勿对x位置和宽度进行硬编码。请改用带尺。

以下是包含这些更改的代码:



var poundDataArray = [{
  Pounds: 10
}, {
  Pounds: 20
}, {
  Pounds: 5
}, {
  Pounds: 8
}, {
  Pounds: 14
}, {
  Pounds: 1
}, {
  Pounds: 12
}];

var w = 350;
var h = 350;
var barPadding = 1;
var margin = {
  top: 5,
  right: 20,
  bottom: 70,
  left: 25
}

var maxPound = d3.max(poundDataArray,
  function(d) {
    return parseInt(d.Pounds)
  }
);

//Y-Axis Code
var yScale = d3.scaleLinear()
  .domain([0, maxPound])
  .range([h - margin.bottom, margin.top]);

var xScale = d3.scaleBand()
  .domain(d3.range(poundDataArray.length))
  .range([margin.left, w - margin.right])
  .padding(.2);

var yAxis = d3.axisLeft()
  .scale(yScale)
  .ticks(5);

//Creating SVG element 
var svg = d3.select("body")
  .append('svg')
  .attr("width", w)
  .attr('height', h)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," +
    margin.top + ")");

svg.selectAll("rect")
  .data(poundDataArray)
  .enter()
  .append("rect")
  .attr('x', function(d, i) {
    return xScale(i);
  })
  .attr('y', function(d) {
    return yScale(d.Pounds);
  })
  .attr('width', xScale.bandwidth())
  .attr('height', function(d) {
    return h - margin.bottom - yScale(d.Pounds);
  })
  .attr('fill', 'steelblue');

//Create Y axis
svg.append("g")
  .attr("class", "axis")
  .attr("transform", "translate(" + margin.left + ",0)")
  .call(yAxis);

<script src="https://d3js.org/d3.v4.min.js"></script>
&#13;
&#13;
&#13;