这更像是对代码审核的请求,但我不能在我的生活中将这个.csv
数据正确地呈现为D3中的折线图...
以下是我写的代码。
到目前为止,我只能渲染y轴和轴标题,但我似乎无法渲染数据。也许我做错了什么,但根本无法看到它。
非常感谢帮助和建议。
// ./weather-app/d3/testing-dsky-d3.js
const fname_forecast = 'forecast-hourly-temp.csv';
const path2File = './csv/';
const parseDateTime = d3.timeParse('%Y-%m-%d %H:%M:%S');
d3.csv(path2File + fname_forecast)
.row((data) => {
return {
date: parseDateTime(data.datetime),
temp: +data.temperature
}
})
.get((err, data) => {
if (err) {
console.log('\nErrors!\n', err)
} else {
console.log(data);
const minDate = d3.min(data, (d) => { return d.date; });
const maxDate = d3.max(data, (d) => { return d.date; });
const minTemp = d3.min(data, (d) => { return d.temp; });
const maxTemp = d3.max(data, (d) => { return d.temp; });
const svg = d3.select('svg'),
margin = { top: 20, right: 20, bottom: 30, left: 50 },
width = +svg.attr('width') - margin.left - margin.right,
height = +svg.attr('height') - margin.top - margin.bottom,
g = svg.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
const x = d3.scaleTime()
.rangeRound([minDate, maxDate])
.domain([minDate, maxDate]);
const y = d3.scaleLinear()
.rangeRound([height, 0])
.domain([height, 0])
const line = d3.line()
.x((d) => { return x(d.date); })
.y((d) => { return y(d.temp); });
g.append('g')
.attr('transform', 'translate(0,' + height + ')')
.call(d3.axisBottom(x))
.select('.domain')
.remove();
g.append('g')
.call(d3.axisLeft(y))
.append('text')
.attr('fill', '#000')
.attr('transform', 'rotate(-90)')
.attr('y', 6)
.attr('dy', '0.71em')
.attr('text-anchor', 'end')
.text('Temperature (degC)');
g.append('path')
.datum(data)
.attr('fill', 'none')
.attr('stroke', 'steelblue')
.attr('stroke-linejoin', 'round')
.attr('stroke-linecap', 'round')
.attr('stroke-width', 1.5)
.attr('d', line);
}
});
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>Test: Rendering DarkSky Data w/ D3</title>
<script type='text/javascript' src='./learn/d3.v4.js'></script>
</head>
<body>
<h1>Test: Rendering DarkSky API Temperature Data w/ <code>D3.js</code></h1>
<hr><br>
<div id='container'>
<svg width='960' height='500'></svg>
</div>
<script type='text/javascript' src='testing-dsky-d3.js'></script>
</body>
.csv
文件datetime,temperature
2018-04-04 12:00:00,46.98
2018-04-04 13:00:00,48.43
2018-04-04 14:00:00,49.63
2018-04-04 15:00:00,49.85
2018-04-04 16:00:00,48.98
2018-04-04 17:00:00,47.95
2018-04-04 18:00:00,47.35
2018-04-04 19:00:00,47.08
2018-04-04 20:00:00,46.79
2018-04-04 21:00:00,46.62
答案 0 :(得分:2)
您需要正确设置比例的域和范围,
下面:
const x = d3.scaleTime()
.rangeRound([minDate, maxDate])
.domain([minDate, maxDate]);
您正在设置一个比例,以便将值从minDate取值到maxDate(域),并将它们映射到从minDate到maxDate(范围)的值。你需要修改它:
const x = d3.scaleTime()
.rangeRound([0,width]) // values to map to (x coordinate values)
.domain([minDate, maxDate]); // extent of input values/values needing scaling
y轴相同:
const y = d3.scaleLinear()
.rangeRound([height, 0])
.domain([height, 0])
您需要区分范围和域名。上面的比例只是取0到height
之间的值,并返回相同的值。
要修复图表,您需要正确设置:
应用这些变化(我硬编码[40,50]的温度域)如下:
const x = d3.scaleTime()
.rangeRound([0,width])
.domain([minDate, maxDate]);
const y = d3.scaleLinear()
.domain([40, 50])
.rangeRound([height, 0])
以及使用您的代码和数据,我得到: