javascript - 在 D3 轴上形成分和秒
问题描述
我正在做一个 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)
});
解决方案
您的问题的任何可能答案都是危险的基于意见的,因为它完全取决于您想要什么:您想将时间视为时间吗?还是您想将时间视为单独的、单独的事件?
这里实际上有三个选项供您选择:
- 使用序数尺度(波段、点...):在这种情况下,每个数据条目将只是一个分类变量。轴中刻度之间的空间将是相同的。
- 使用线性刻度:这允许轴中刻度的不同距离。但是,这些值不会是时间,您必须创建一个数学来设置值(最简单的可能是计算秒数)。
- 使用时间尺度:这有一个优势,那就是您将时间视为时间。然而,主要的缺点正是前面的陈述:时间是一个复杂的野兽,你会有闰年、夏令时、时区差异等......
由于线性比例很容易创建(而序数比例更简单),这里有一个答案,展示了如何使用时间比例来做到这一点。
假设你有这个数据数组:
var data = ["12:32", "21:05", "24:56", "36:30", "45:14", "71:11"];
第一步是解析日期:
var specifier = "%M:%S";
var parsedData = data.map(function(d) {
return d3.timeParse(specifier)(d)
});
然后创建规模:
var scale = d3.scaleTime()
.domain(d3.extent(parsedData));
为此,我们必须设置tickValues
使用我们解析的数据数组,并将刻度格式化为分钟和秒:
var axis = d3.axisBottom(scale)
.tickValues(parsedData)
.tickFormat(function(d){
return d3.timeFormat(specifier)(d)
});
结果如下:
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>
如您所见,刻度线在此处的间距正确。但是我们有一个问题:这些刻度是实际日期(如果您检查代码,您会看到年份是 1900 年)。因此,最后一个刻度,应该是 71 分 11 秒,显示为11:11
,因为它是下一小时的第 11 分钟。
一个简单的解决方案是引用原始字符串数组:
.tickFormat(function(d,i) {
return data[i]
});
结果如下:
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>
推荐阅读
- laravel - 如何解决这个错误 传递给 Illuminate\Database\Grammar::parameterize() 的参数 1 必须是数组类型,给定字符串
- r - R中数据框列表的子集
- api - 由于 public_profile,FB.AppRequest 不起作用
- c# - 如何使用 dotnet CLI 构建 .NET Framework 4.8 应用程序?
- python - 如何在 PySide6 中将 QDate 转换为 Python 日期对象
- regex - 正则表达式提取特殊情况的子字符串
- azure-devops - 如何使用 AzDevOps Pipeline 重新部署 Azure 资源?
- c# - 多 Blazor 应用同一主机 + Azure 广告身份验证
- python - 井字游戏添加异常处理和警告功能
- flutter - 如何在 listviewbuilder 的 textformfield 中添加验证?