gpt4 book ai didi

javascript - 如何在组合图表(条形图和线条)中分别将 x 轴与条形图对齐?

转载 作者:行者123 更新时间:2023-11-30 14:17:32 26 4
gpt4 key购买 nike

我有一个基于 D3.js 的组合/条形图和折线图。 x 轴域包含最小和最大日期,条形图基于值。但最后一根柱线(矩形)在图表之外。我可以通过强制(手动)将其引入,但它不会反射(reflect)数据。

var data = [
{
fcst_valid_local: "2018-11-13T14:00:00-0600",
pop: 20,
rh: 67,
temp: 38,
wspd: 7
},
{
fcst_valid_local: "2018-11-14T15:00:00-0600",
pop: 15,
rh: 50,
temp: 39,
wspd: 8
},
{
fcst_valid_local: "2018-11-15T16:00:00-0600",
pop: 10,
rh: 90,
temp: 40,
wspd: 9
}
];

// Margins, width and height.
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = 500 - margin.left - margin.right,
height = 200 - margin.top - margin.bottom;

// Date parsing.
const parseDate = d3.timeParse("%Y-%m-%dT%H:%M:%S%Z");
data.forEach(function (d) {
d.date = parseDate(d.fcst_valid_local);
});

// Set scale domains.
var x = d3.scaleTime().range([0, width])
.domain(d3.extent(data, function (d) {
return d.date;
}));

var y0 = d3.scaleLinear().range([height, 0]).domain([0, 100]);
const y1 = d3.scaleLinear()
.range([height, 0])
.domain([0, d3.max(data, (d) => d.pop)]);

// Construct our SVG object.
const svg = d3.select('svg')
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append('g').attr('class', 'container')
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");

// Set x, y-left and y-right axis.
var xAxis = d3.axisBottom(x)
.ticks(d3.timeDay.every(1))
// .tickFormat(d3.timeFormat('%b %d, %H:%M'))
.tickSize(0).tickPadding(10);
var y0Axis = d3.axisLeft(y0)
.ticks(5).tickSize(0);
var y1Axis = d3.axisRight(y1).ticks(5).tickSize(0);

svg.append("g")
.attr("class", "x-axis axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y-axis axis")
.attr("transform", "translate(" + 0 + ", 0)")
.call(y0Axis);
svg.append("g")
.attr("class", "y-axis axis")
.attr("transform", "translate(" + width + ", 0)")
.call(y1Axis);

// Draw bars.
var bars = svg.selectAll(".precips")
.data(data);

bars.exit().remove();

bars.enter().append("rect")
.attr("class", "precip")
.attr("width", width / data.length - 50)
.attr("x", function (d) {
return x(d.date);
})
.attr("y", height)
.transition().duration(1000)
.attr("y", function (d) {
return y0(d.pop);
})
.attr("height", function (d) {
return height - y0(d.pop);
});

const lineRH = d3.line()
.x((d) => x(d['date']))
.y(d => y0(d['rh']));

svg.append('path')
.datum(data)
.attr('class', 'line')
.attr('fill', 'none')
.attr('stroke', 'red')
.attr('stroke-linejoin', 'round')
.attr('stroke-linecap', 'round')
.attr('stroke-width', 1.5)
.attr('d', lineRH);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>

最佳答案

虽然答案已被接受,但我想让您知道您不必操作 data(因为它也可能从 API 获取)但您可以尝试使用 x.domain(),因为它是关于在此处设置正确的 domain 的。

  1. 尝试使用 d3 time_nice将时间尺度域四舍五入
  2. 玩转 d3 time更改日期的方法(这里有很多)

下面是使用上述第二种方法并设置 x 域的示例:

var x = d3.scaleTime().range([0, width])
.domain([d3.min(data, function (d) {
return d.date;
}), d3.timeDay.offset(d3.max(data, function (d) { return d.date; }), 1)]);

说明:这是将数据的最大日期偏移 1 天,因此新的 x.domain() 将显示为:

(2) [Tue Nov 13 2018 15:00:00 GMT-0500 (Eastern Standard Time), Fri Nov 16 2018 17:00:00 GMT-0500 (Eastern Standard Time)]

结果如下图:

var data = [
{
fcst_valid_local: "2018-11-13T14:00:00-0600",
pop: 20,
rh: 67,
temp: 38,
wspd: 7
},
{
fcst_valid_local: "2018-11-14T15:00:00-0600",
pop: 15,
rh: 50,
temp: 39,
wspd: 8
},
{
fcst_valid_local: "2018-11-15T16:00:00-0600",
pop: 10,
rh: 90,
temp: 40,
wspd: 9
}
];

// Margins, width and height.
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = 500 - margin.left - margin.right,
height = 200 - margin.top - margin.bottom;

// Date parsing.
const parseDate = d3.timeParse("%Y-%m-%dT%H:%M:%S%Z");
data.forEach(function (d) {
d.date = parseDate(d.fcst_valid_local);
});

// Set scale domains.
var x = d3.scaleTime().range([0, width])
.domain([d3.min(data, function (d) {
return d.date;
}), d3.timeDay.offset(d3.max(data, function (d) { return d.date; }), 1)]);

var y0 = d3.scaleLinear().range([height, 0]).domain([0, 100]);
const y1 = d3.scaleLinear()
.range([height, 0])
.domain([0, d3.max(data, (d) => d.pop)]);
//console.log(x.domain());
// Construct our SVG object.
const svg = d3.select('svg')
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append('g').attr('class', 'container')
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");

// Set x, y-left and y-right axis.
var xAxis = d3.axisBottom(x)
.ticks(d3.timeDay.every(1))
// .tickFormat(d3.timeFormat('%b %d, %H:%M'))
.tickSize(0).tickPadding(10);
var y0Axis = d3.axisLeft(y0)
.ticks(5).tickSize(0);
var y1Axis = d3.axisRight(y1).ticks(5).tickSize(0);

svg.append("g")
.attr("class", "x-axis axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y-axis axis")
.attr("transform", "translate(" + 0 + ", 0)")
.call(y0Axis);
svg.append("g")
.attr("class", "y-axis axis")
.attr("transform", "translate(" + width + ", 0)")
.call(y1Axis);

// Draw bars.
var bars = svg.selectAll(".precips")
.data(data);

bars.exit().remove();

bars.enter().append("rect")
.attr("class", "precip")
.attr("width", width / data.length - 50)
.attr("x", function (d) {
return x(d.date);
})
.attr("y", height)
.transition().duration(1000)
.attr("y", function (d) {
return y0(d.pop);
})
.attr("height", function (d) {
return height - y0(d.pop);
});

const lineRH = d3.line()
.x((d) => x(d['date']) + (width / data.length - 50)/2)
.y(d => y0(d['rh']));

svg.append('path')
.datum(data)
.attr('class', 'line')
.attr('fill', 'none')
.attr('stroke', 'red')
.attr('stroke-linejoin', 'round')
.attr('stroke-linecap', 'round')
.attr('stroke-width', 1.5)
.attr('d', lineRH);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>

我还尝试使用 .nice(),一个有趣的部分是在 .nice() 中使用 d3 时间间隔。随意尝试这些,如果您有任何问题,请告诉我。

另外,我在线生成器 fn 中用 barwidth/2 偏移了 line(路径)。

d3.line()
.x((d) => x(d['date']) + (width / data.length - 50)/2)

希望这也有帮助。

关于javascript - 如何在组合图表(条形图和线条)中分别将 x 轴与条形图对齐?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53325104/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com