gpt4 book ai didi

javascript - D3.JS Y轴标签问题

转载 作者:行者123 更新时间:2023-11-30 14:55:58 25 4
gpt4 key购买 nike

首先,我是 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 图表从顶部的 0 和底部的 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 或高度值中,并且花了一些时间在那里乱搞,但没有结果。

最佳答案

这不是 D3 问题,而是 SVG 特性:在 SVG 中,原点 (0,0) 位于左上角,而不是左下角,就像在常见的笛卡尔坐标中一样飞机。这就是为什么使用 [0, h] 作为范围使轴看起来倒转的原因……实际上,它没有倒转:这是 SVG 中的正确方向。顺便说一句,HTML5 Canvas 具有相同的坐标系,使用 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>

关于javascript - D3.JS Y轴标签问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47274701/

25 4 0