我正在开发一个D3项目,我有JSON格式的时间(分钟和秒),如下所示:
"Time": "36:50"
如何在D3图形的y轴上以该格式绘制时间?我应该使用d3.scaleTime
或d3.scaleLinear
作为轴吗?如何制作以minute:second
格式显示时间的刻度,就像它采用JSON格式一样?
修改:
这是我到目前为止的尺度/轴:
//Format data for X Axis
var yearFormat = "%Y";
var parsedYear = years.map(function(d) {
return d3.timeParse(yearFormat)(d)
});
var x = d3.scaleTime()
.range([0, width])
.domain(d3.extent(parsedYear));
// Format data for Y Axis
var specifier = "%M:%S";
var parsedTime = times.map(function(d) {
return d3.timeParse(specifier)(d)
})
var y = d3.scaleTime()
.range([height, 0])
.domain(d3.extent(parsedTime));
// X Axis
g.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.attr("stroke-width", 2)
.style("font-size", ".6em")
// Y Axis
g.append("g")
.call(d3.axisLeft(y))
.attr("stroke-width", 2)
.style("font-size", ".6em")
.tickValues(parsedTime)
.tickFormat(function(d){
return d3.timeFormat(specifier)(d)
});
答案 0 :(得分:3)
Any possible answer for your question is dangerously opinion-based, because it depends on exactly what you want: do you want to treat time as time? Or do you want to treat time as just separate, individual events?
There are actually three options for you here:
Since the linear scale is quite simple to create (and the ordinal scale is even more simple), here is an answer showing how to do it with a time scale.
Suppose you have this data array:
var data = ["12:32", "21:05", "24:56", "36:30", "45:14", "71:11"];
The first step is parsing the dates:
var specifier = "%M:%S";
var parsedData = data.map(function(d) {
return d3.timeParse(specifier)(d)
});
And then creating the scale:
var scale = d3.scaleTime()
.domain(d3.extent(parsedData));
For this to work, we'll have to set the tickValues
using our parsed data array, and formatting the ticks for minutes and seconds:
var axis = d3.axisBottom(scale)
.tickValues(parsedData)
.tickFormat(function(d){
return d3.timeFormat(specifier)(d)
});
Here is the result:
var data = ["12:32", "21:05", "24:56", "36:30", "45:14", "71:11"];
var specifier = "%M:%S";
var svg = d3.select("svg");
var parsedData = data.map(function(d) {
return d3.timeParse(specifier)(d)
});
var scale = d3.scaleTime()
.domain(d3.extent(parsedData))
.range([30, 470]);
var axis = d3.axisBottom(scale)
.tickValues(parsedData)
.tickFormat(function(d) {
return d3.timeFormat(specifier)(d)
});
var gX = svg.append("g")
.attr("transform", "translate(0,50)")
.call(axis)
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg width="500" height="100"></svg>
As you can see, the ticks are correctly spaced here. But we have a problem: those ticks are actual dates (if you inspect the code, you'll see that the year is 1900). Because of that, the last tick, which should be 71 minutes and 11 seconds, is shown as 11:11
, because it is the eleventh minute of the next hour.
A simple solutions is referencing the original array of strings:
.tickFormat(function(d,i) {
return data[i]
});
And here is the result:
var data = ["12:32", "21:05", "24:56", "36:30", "45:14", "71:11"];
var specifier = "%M:%S";
var svg = d3.select("svg");
var parsedData = data.map(function(d) {
return d3.timeParse(specifier)(d)
});
var scale = d3.scaleTime()
.domain(d3.extent(parsedData))
.range([30, 470]);
var axis = d3.axisBottom(scale)
.tickValues(parsedData)
.tickFormat(function(d, i) {
return data[i]
});
var gX = svg.append("g")
.attr("transform", "translate(0,50)")
.call(axis)
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg width="500" height="100"></svg>