python-3.x - Flask & Python:如何使用格式 HH:MM: SS.SSS in Flask 绘制带有月份 x 轴和 y 轴(数据)和时间的图表
问题描述
我目前正在使用 Flask 和 Chart.js 来生成图形。基本上我有一个数据库(sqlite)来存储游泳比赛中获得的时间。时间格式为“HH:MM:SS.SSS” 例如,在 50 米自由泳中我没有问题,因为时间格式为“SS.SS”(例如 26.94),我可以在 Flask 中生成图表Chart.js 因为我可以将 26.94 转换为数字并得到一个图表,其中 x 轴代表月份,y 轴代表时间(例如 26.94)。但是,在像“00:08:23.78”这样的时间的情况下,我需要在 y 轴上相对于到达时间的 x 轴上的月份来绘制该时间。我仍然无法想象 Chart.js 的解决方案。任何指南将不胜感激。
@app.route("/simple_chart")
def chart():
legend = 'Monthly performance at 50m Freestyle'
labels = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dic"]
values = [26.94, 26.70, 26.80, 27.40, 26.45, 26.43, 26.30, 26.25, 26.20, 26.35, 26.00, 25.00]
return render_template('chart.html', values=values, labels=labels, legend=legend)
chart.html文件源代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Chart.js Example</title>
<!-- import plugin script -->
<script src='static/Chart.min.js'></script>
</head>
<body>
<h1>50 m. Free Style</h1>
<!-- bar chart canvas element -->
<canvas id="myChart" width="600" height="400"></canvas>
<p id="caption">Data obtained from swimming competitions.</p>
<script>
// Global parameters:
// do not resize the chart canvas when its container does (keep at 600x400px)
Chart.defaults.global.responsive = false;
// define the chart data
var chartData = {
labels : [{% for item in labels %}
"{{item}}",
{% endfor %}],
datasets : [{
label: '{{ legend }}',
fill: true,
lineTension: 0.1,
backgroundColor: "rgba(75,192,192,0.4)",
borderColor: "rgba(75,192,192,1)",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "rgba(75,192,192,1)",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(75,192,192,1)",
pointHoverBorderColor: "rgba(220,220,220,1)",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data : [{% for item in values %}
{{item}},
{% endfor %}],
spanGaps: false
}]
}
// get chart canvas
var ctx = document.getElementById("myChart").getContext("2d");
// create the chart using the chart canvas
var myChart = new Chart(ctx, {
type: 'line',
data: chartData,
});
</script>
</body>
解决方案
附上一张图表的截图,显示了女子 800 米自由泳的记录进展情况。
源代码在最合适的块中包含注释,以在必要时阐明实现。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<link rel="stylesheet" href="/static/style.css" />
<script data-require="jquery" data-semver="3.1.1" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://npmcdn.com/moment@2.14.1"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
<script>
$(function(){
const ctx = document.getElementById('myChart').getContext('2d');
let years = [
"1978",
"1978",
"1987",
"1987",
"1988",
"1989",
"2008",
"2013",
"2014",
"2015",
"2016",
"2016"
];
let times = [
"00:08:30.53",
"00:08:24.62",
"00:08:22.44",
"00:08:19.53",
"00:08:17.12",
"00:08:16.22",
"00:08:14.10",
"00:08:13.86",
"00:08:11.00",
"00:08:07.39",
"00:08:06.68",
"00:08:04.79"
];
let data = years.map((year, index) => ({
x: moment(`${year}-01-01`),
y: moment(`1970-02-01 ${times[index]}`).valueOf()
}));
let bckColors = [
"#66FF00", // Bright Green
"#1974D2", // Bright Navy Blue
"#08E8DE", // Bright Turquoise
"#FFF000", // Yellow Rose
"#FFAA1D", // Bright Yellow (Crayola)
"#FF007F", // Bright Pink
"#91aaff",
"#ff9e9e",
"#ff80c5",
"#7afbff",
"#8aff9c",
"#edc065"
];
let myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
label: "Time progression in the 800m. freestyle Women",
// SEE: https://encycolorpedia.com/
// to assign rgba() colors
// 'backgroundColor' fill color of the area under the curve that joins the points
backgroundColor: 'rgba(17, 67, 116, 0.6)', // Sailboat Blue 0.6 reduce opacity
// To reduce opacity SEE: https://stackoverflow.com/questions/45104743/draw-two-plots-using-chartjs-over-one-another-with-transparency
// 'borderColor' color of the line connecting the points
borderColor: 'rgba(254, 254, 250, 1.0)', // Baby Powder
pointBackgroundColor: bckColors,
data: data,
pointBorderWidth: 2,
pointRadius: 5,
pointHoverRadius: 7
}]
},
options:{
legend:{
labels:{
fontFamily:'Courier',
fontColor: 'black',
fontSize: 18
}
},
scales: {
xAxes:[{
type: 'time',
position: 'bottom',
time:{
displayFormats: {
years: 'YYYY'
},
unit: 'year'
},
ticks: {
fontFamily:'Courier',
fontColor: 'black',
fontSize: 12,
// Display the labels in x-Axis
// jumping from three years to three years
// SEE:https://stackoverflow.com/questions/61847921/chart-js-how-i-change-the-x-axes-ticks-labels-alignment-in-any-sizes
autoSkip: true,
autoSkipPadding: 75,
},
scaleLabel:{
// x-axis label
fontFamily:'Courier',
fontColor: 'black',
fontSize: 14,
display: true,
labelString: 'Year'
}
}],
yAxes:[{
type: 'linear',
position: 'left',
ticks:{
fontFamily:'Courier',
fontColor: 'black',
fontSize: 12,
// fix y-Axis time interval.
// This interval must go from (mm:ss.SS)
// "00:00.00" to (mm:ss.SS) "10:00.00"
min: moment('1970-02-01 00:08:00.00').valueOf(),
max: moment('1970-02-01 00:08:31.00').valueOf(),
beginAtZero:false,
callback: value => {
let date = moment(value);
if(date.diff(moment('1970-02-01 00:10:00.00'), 'seconds') === 0) {
return null;
}
// SEE: https://flaviocopes.com/momentjs/
// Moment provides a constant
// 'HTML5_FMT.TIME_MS'
// to format date as HH:mm:ss.SSS
// Example: 16:34:10.234
return moment(date,'HTML5_FMT.TIME_MS').format('mm:ss.SS')
}
},
scaleLabel:{
// y-axis label
fontFamily:'Courier',
fontColor: 'black',
fontSize: 14,
display: true,
labelString: 'Time'
}
}]
},
tooltips:{
callbacks:{
title: function(tooltipItems, data) {
// Return value for title (xlabel)
// SEE: callback function to change
// title of tooltip (tooltipItems[0].xLabel)
// https://stackoverflow.com/questions/38819171/chart-js-2-0-how-to-change-title-of-tooltip
// SEE: https://flaviocopes.com/momentjs/
// Moment provides the functions to format
// tooltipItems[0].xLabel (Date) to 'YYYY' Example: 2016
return moment(tooltipItems[0].xLabel).format("YYYY")
},
label: function(tooltipItem, data) {
// Return value for (yLabel)
// SEE: callback function to convert timestamp (tooltipItem.yLabel) to mm:ss.SS
// https://stackoverflow.com/questions/19485353/function-to-convert-timestamp-to-human-date-in-javascript/34900794
return ' Time : ' + moment(tooltipItem.yLabel).format("mm:ss.SS")
},
}
}
}
});
});
</script>
</head>
<body>
<div class = "container">
<canvas style = "background-color: grey;" id="myChart"></canvas>
</div>
</body>
推荐阅读
- java - java代码计算排序算法的运行时间
- sql - PostgreSQL 中的时间窗口
- sql - 如果没有信息,如何从下一行获取信息并填写?
- python - 如何删除与子字符串部分匹配的熊猫行?
- openstreetmap - 本地计算机和服务器之间的 Overpass API 速率限制不一致?
- firebase - npm 警告安装 firebase
- rust - 为 Cargo.toml 提供 fmt 预提交钩子的位置
- java - Spring Framework - Kotlin - 将实体保存到 XML
- html - 居中和右对齐 flexbox 元素与 text-oveflow 并在左侧占用空白空间
- ios - 如何从 simctl 命令行检索 ios 设备屏幕分辨率