d3.js - 将字符串时间戳转换为小时轴
问题描述
我正在尝试基于 d3 中的两个时间戳创建散点图,但我不确定使用 d3-time-format 方法正确解析时间戳格式中的值并基于 24 构建范围的正确方法-小时期间。到目前为止,我构建了一个函数来遍历我的数组并使用 d3 方法将字符串转换为 d3 可读格式,但我似乎可以弄清楚如何格式化输出,以便将其从日期格式转换为时间格式。我的问题是 d3 接受时间格式吗?以及如何将日期对象转换为时间对象?目前我有一个 y 轴,它显示了多年的刻度。
提供的是我的完整代码:
<meta charset="utf-8">
<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>
<style>
div.tooltip {
position: absolute;
text-align: center;
width: 100px;
height: 30px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
</style>
<script>
var data = [
{
"x": "23:19:30",
"y": "08:07:00"
},
{
"x": "22:55:30",
"y": "06:08:00"
},
{
"x": "21:14:30",
"y": "06:13:30"
},
{
"x": "21:24:30",
"y": "06:04:30"
},
{
"x": "21:24:00",
"y": "06:04:00"
},
{
"x": "21:28:00",
"y": "06:09:00"
},
{
"x": "23:23:30",
"y": "08:20:30"
},
{
"x": "23:47:00",
"y": "08:01:30"
},
{
"x": "00:03:00",
"y": "06:49:30"
},
{
"x": "21:46:00",
"y": "06:21:00"
},
{
"x": "21:58:00",
"y": "06:02:30"
},
{
"x": "21:33:00",
"y": "05:56:00"
},
{
"x": "22:33:00",
"y": "06:15:30"
},
{
"x": "23:49:00",
"y": "07:10:30"
},
{
"x": "23:46:30",
"y": "08:35:30"
},
{
"x": "23:15:30",
"y": "05:59:30"
},
{
"x": "21:26:00",
"y": "06:05:00"
},
{
"x": "21:26:30",
"y": "05:54:00"
},
{
"x": "21:06:00",
"y": "05:53:00"
},
{
"x": "21:25:00",
"y": "05:47:30"
},
{
"x": "00:29:30",
"y": "08:59:30"
},
{
"x": "01:14:00",
"y": "08:09:30"
},
{
"x": "23:12:30",
"y": "06:06:30"
},
{
"x": "21:26:00",
"y": "05:52:30"
},
{
"x": "21:18:30",
"y": "05:47:00"
},
{
"x": "20:54:30",
"y": "07:07:30"
},
{
"x": "21:36:00",
"y": "05:53:30"
},
{
"x": "00:28:00",
"y": "08:00:00"
},
{
"x": "23:21:30",
"y": "07:58:30"
},
{
"x": "21:34:00",
"y": "05:51:00"
},
{
"x": "21:23:30",
"y": "05:58:00"
},
{
"x": "21:05:30",
"y": "05:53:00"
},
{
"x": "21:33:30",
"y": "05:39:30"
},
{
"x": "23:49:30",
"y": "06:50:00"
},
{
"x": "01:11:00",
"y": "08:37:30"
},
{
"x": "22:34:30",
"y": "05:15:00"
},
{
"x": "22:49:30",
"y": "05:55:00"
},
{
"x": "22:06:30",
"y": "06:03:00"
},
{
"x": "21:32:30",
"y": "06:01:00"
},
{
"x": "21:49:00",
"y": "05:39:30"
},
{
"x": "22:47:30",
"y": "08:27:30"
},
{
"x": "21:26:30",
"y": "05:51:00"
},
{
"x": "21:47:30",
"y": "05:51:00"
},
{
"x": "21:28:00",
"y": "05:47:30"
},
{
"x": "21:32:00",
"y": "05:47:30"
},
{
"x": "21:13:30",
"y": "05:46:00"
},
{
"x": "23:42:30",
"y": "06:45:00"
},
{
"x": "21:33:00",
"y": "05:48:00"
},
{
"x": "21:45:00",
"y": "05:51:00"
},
{
"x": "21:29:30",
"y": "06:06:00"
},
{
"x": "21:16:00",
"y": "05:43:00"
},
{
"x": "21:14:00",
"y": "05:46:30"
},
{
"x": "00:01:30",
"y": "07:25:30"
},
{
"x": "02:24:00",
"y": "10:35:30"
},
{
"x": "22:29:30",
"y": "07:04:00"
},
{
"x": "21:43:30",
"y": "05:51:00"
},
{
"x": "21:31:30",
"y": "05:45:00"
},
{
"x": "22:16:30",
"y": "05:50:30"
},
{
"x": "21:59:00",
"y": "05:47:00"
},
{
"x": "02:55:30",
"y": "11:15:30"
},
{
"x": "02:57:00",
"y": "07:23:00"
},
{
"x": "21:49:30",
"y": "06:48:30"
},
{
"x": "21:31:30",
"y": "05:26:30"
}
]
// D3 date parser
for (var i=0; i < data.length; i++){
var parser = d3.timeParse("%I:%M:%S")
data[i].x = parser(data[i].x);
data[i].y = parser(data[i].y);
}
console.log(data)
var margin = { top: 10, right: 30, bottom: 30, left: 60 }
var width = 800 - margin.left - margin.right;
var height = 800 - margin.top - margin.bottom;
// Define the div for the tooltip
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var svg = d3.select("#my_dataviz")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // translate(margin left, margin top)
var x = d3.scaleTime()
.domain([d3.min(data, function(d) { return d.date }), d3.max(data, function(d) { return d.date })])
.range([0, width]);
svg.append("g")
.attr("transform", "translate(" + 0 + "," + height + ")")
.call(d3.axisBottom(x))
// .tickFormat(d3.time.format);
// text label for the x axis
svg.append("text")
.attr("transform",
"translate(" + (width/2) + " ," + (height + margin.top + 20) + ")")
.style("text-anchor", "middle")
.text("Date");
var y = d3.scaleTime()
.domain([0, d3.max(data, function(d){ return +d.y })])
.range([height, 0]);
svg.append("g")
.call(d3.axisLeft(y));
// text label for the y axis
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x",0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Time Asleep (Minutes)");
// Add line path
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 1.5)
.attr("d", d3.line()
.x(function(d) { return x(d.date) })
.y(function(d) { return y(d.y) })
);
// Add the scatterplot (data points)
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 3)
.attr("cx", function(d){ return x(d.date) })
.attr("cy", function(d){ return y(d.y) })
// Add tooltip on hover
.on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9);
div.html(d.x + "<br/>" + d.label)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 30) + "px")
})
// Remove tooltip after hover
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
</script>
解决方案
要格式化日期,请使用d3.timeParse
. 这会将任何日期字符串解析为 Date 对象。D3 可以理解和使用timeScale
.
我已将您的原始数据重命名为rawData
. 我们还需要按 X 轴对数据进行排序:
var toDate = d3.timeParse("%H:%M:%S")
var data = rawData.map(d => ({
x: toDate(d.x),
y: toDate(d.y),
})).sort((a, b) => d3.descending(a.x, b.x)
要计算域,请使用d3.extent
which 将自动计算域。
var x = d3.scaleTime()
.domain(d3.extent(data, d => d.x))
.range([0, width]);
<head></head>
<meta charset="utf-8">
<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>
<style>
div.tooltip {
position: absolute;
text-align: center;
width: 100px;
height: 30px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
</style>
<script>
var rawData = [
{
"x": "23:19:30",
"y": "08:07:00"
},
{
"x": "22:55:30",
"y": "06:08:00"
},
{
"x": "21:14:30",
"y": "06:13:30"
},
{
"x": "21:24:30",
"y": "06:04:30"
},
{
"x": "21:24:00",
"y": "06:04:00"
},
{
"x": "21:28:00",
"y": "06:09:00"
},
{
"x": "23:23:30",
"y": "08:20:30"
},
{
"x": "23:47:00",
"y": "08:01:30"
},
{
"x": "00:03:00",
"y": "06:49:30"
},
{
"x": "21:46:00",
"y": "06:21:00"
},
{
"x": "21:58:00",
"y": "06:02:30"
},
{
"x": "21:33:00",
"y": "05:56:00"
},
{
"x": "22:33:00",
"y": "06:15:30"
},
{
"x": "23:49:00",
"y": "07:10:30"
},
{
"x": "23:46:30",
"y": "08:35:30"
},
{
"x": "23:15:30",
"y": "05:59:30"
},
{
"x": "21:26:00",
"y": "06:05:00"
},
{
"x": "21:26:30",
"y": "05:54:00"
},
{
"x": "21:06:00",
"y": "05:53:00"
},
{
"x": "21:25:00",
"y": "05:47:30"
},
{
"x": "00:29:30",
"y": "08:59:30"
},
{
"x": "01:14:00",
"y": "08:09:30"
},
{
"x": "23:12:30",
"y": "06:06:30"
},
{
"x": "21:26:00",
"y": "05:52:30"
},
{
"x": "21:18:30",
"y": "05:47:00"
},
{
"x": "20:54:30",
"y": "07:07:30"
},
{
"x": "21:36:00",
"y": "05:53:30"
},
{
"x": "00:28:00",
"y": "08:00:00"
},
{
"x": "23:21:30",
"y": "07:58:30"
},
{
"x": "21:34:00",
"y": "05:51:00"
},
{
"x": "21:23:30",
"y": "05:58:00"
},
{
"x": "21:05:30",
"y": "05:53:00"
},
{
"x": "21:33:30",
"y": "05:39:30"
},
{
"x": "23:49:30",
"y": "06:50:00"
},
{
"x": "01:11:00",
"y": "08:37:30"
},
{
"x": "22:34:30",
"y": "05:15:00"
},
{
"x": "22:49:30",
"y": "05:55:00"
},
{
"x": "22:06:30",
"y": "06:03:00"
},
{
"x": "21:32:30",
"y": "06:01:00"
},
{
"x": "21:49:00",
"y": "05:39:30"
},
{
"x": "22:47:30",
"y": "08:27:30"
},
{
"x": "21:26:30",
"y": "05:51:00"
},
{
"x": "21:47:30",
"y": "05:51:00"
},
{
"x": "21:28:00",
"y": "05:47:30"
},
{
"x": "21:32:00",
"y": "05:47:30"
},
{
"x": "21:13:30",
"y": "05:46:00"
},
{
"x": "23:42:30",
"y": "06:45:00"
},
{
"x": "21:33:00",
"y": "05:48:00"
},
{
"x": "21:45:00",
"y": "05:51:00"
},
{
"x": "21:29:30",
"y": "06:06:00"
},
{
"x": "21:16:00",
"y": "05:43:00"
},
{
"x": "21:14:00",
"y": "05:46:30"
},
{
"x": "00:01:30",
"y": "07:25:30"
},
{
"x": "02:24:00",
"y": "10:35:30"
},
{
"x": "22:29:30",
"y": "07:04:00"
},
{
"x": "21:43:30",
"y": "05:51:00"
},
{
"x": "21:31:30",
"y": "05:45:00"
},
{
"x": "22:16:30",
"y": "05:50:30"
},
{
"x": "21:59:00",
"y": "05:47:00"
},
{
"x": "02:55:30",
"y": "11:15:30"
},
{
"x": "02:57:00",
"y": "07:23:00"
},
{
"x": "21:49:30",
"y": "06:48:30"
},
{
"x": "21:31:30",
"y": "05:26:30"
}
]
// D3 date parser
var toDate = d3.timeParse("%H:%M:%S")
var data = rawData.map(d => ({
x: toDate(d.x),
y: toDate(d.y),
})).sort((a, b) => d3.descending(a.x, b.x))
console.log(data[0])
var margin = { top: 10, right: 30, bottom: 30, left: 60 }
var width = 800 - margin.left - margin.right;
var height = 800 - margin.top - margin.bottom;
// Define the div for the tooltip
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var svg = d3.select("#my_dataviz")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // translate(margin left, margin top)
var x = d3.scaleTime()
.domain(d3.extent(data, d => d.x))
.range([0, width]);
svg.append("g")
.attr("transform", "translate(" + 0 + "," + height + ")")
.call(d3.axisBottom(x))
// .tickFormat(d3.time.format);
// text label for the x axis
svg.append("text")
.attr("transform",
"translate(" + (width/2) + " ," + (height + margin.top + 20) + ")")
.style("text-anchor", "middle")
.text("Date");
var y = d3.scaleTime()
.domain(d3.extent(data, d => d.y))
.range([height, 0]);
svg.append("g")
.call(d3.axisLeft(y));
// text label for the y axis
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x",0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Time Asleep (Minutes)");
// Add line path
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 1.5)
.attr("d", d3.line()
.x(function(d) { return x(d.x) })
.y(function(d) { return y(d.y) })
);
// Add the scatterplot (data points)
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 3)
.attr("cx", function(d){ return x(d.x) })
.attr("cy", function(d){ return y(d.y) })
// Add tooltip on hover
.on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9);
div.html(d.x + "<br/>" + d.label)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 30) + "px")
})
// Remove tooltip after hover
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
</script>
推荐阅读
- google-bigquery - 如何在 BigQuery 中设置表级写入权限?
- javascript - 尝试调用 newGame 函数时收到错误
- javascript - Javascript 函数(....参数)
- stripe-payments - Stripe Checkout 会话后如何在发票上获取客户信息
- css - Angular 7 - 根据条件更改 Mat-select-value 的颜色
- c++ - 指向一维/二维数组的指针的基本类型是什么,为什么需要双重取消引用?
- javascript - 我正在使用 node.js,这是一个预设,但它似乎不起作用
- javascript - 获取购物车中产品的尺寸
- c - 将 VS Code 设置为 Arduino IDE 后产生错误
- javascript - jQuery AJAX 在 Safari 浏览器中不起作用