如何动态绘制表中的点?该表有两列专用于 x 和 y 坐标,还有一列用于持续时间。
例
假设我有下面显示的表格。"日期"和"工作量"列将构成折线图的 x,y 坐标(时间戳、工作量)。此折线图将包含基于"时间戳"和"工作量"列中的累积总计的数据点。"持续时间"列将确定条目对折线图的数据点产生影响的时间长度。因此,根据此表,我想要一个折线图,其中包含"数据点"下列出的坐标。
时间戳工作量持续时间
4/13/2016 12:13:12.15 10 100
4/13/2016 12:13:12.80 12 100
4/13/2016 12:13:13.15 30 100
2016/4/13 12:13:13.80 50 100
数据点:
(4/13/2016 12:13:12.15, 10)
(4/13/2016 12:13:12.80, 22)
(4/13/2016 12:13:13.15, 42)
(4/13/2016 12:13:13.80, 80)
Highcharts演示精确地展示了如何使用静态HTML表实现此目的:http://www.highcharts.com/demo/column-parsed。
我使用您的示例数据创建了一个小提琴,并根据您的要求将其绘制为折线图:http://jsfiddle.net/brightmatrix/qgvkp0t0/
您的数据表的编码将类似于以下内容:
<table id="datatable">
<thead>
<tr>
<th>Time</th>
<th>Effort</th>
</tr>
</thead>
<tbody>
<tr>
<th>4/13/2016 12:13:12.15</th>
<td>10</td>
</tr>
<tr>
<th>4/13/2016 12:13:12.80</th>
<td>22</td>
</tr>
<tr>
<th>4/13/2016 12:13:13.15</th>
<td>42</td>
</tr>
<tr>
<th>4/13/2016 12:13:13.80</th>
<td>80</td>
</tr>
</tbody>
</table>
然后,您将使用以下代码创建图表。请注意调用 HTML 表 ID 的 data
属性:
$(function () {
$('#container').highcharts({
data: {
table: 'datatable'
},
chart: {
type: 'line'
},
title: {
text: 'Data extracted from a HTML table in the page'
},
xAxis: {
type: 'category'
},
yAxis: {
allowDecimals: false,
title: {
text: 'Units'
}
},
tooltip: {
formatter: function () {
return '<b>' + this.series.name + '</b><br/>' + this.point.y;
}
}
});
});
需要注意的一点是:无需任何修改,时间戳数据将作为datetime
类型读取到 x 轴中。这会给您之间的日期或时间留下空点。
在我的示例中,我显式将 x 轴类型设置为 category
,以便图表上每个数据点只有一个图。
现在,要使 x 轴标签以更易读的格式显示,您可以浏览xAxis.labels.formatter
属性 (http://api.highcharts.com/highcharts#xAxis.labels.formatter) 和Highcharts.dateFormat()
函数 (http://api.highcharts.com/highcharts#Highcharts.dateFormat)。
更新(2016 年 7 月 13 日):我已经能够解决原始海报的要求,即根据 HTML 表中的数据添加累积点,但不能删除早于当前数据点持续时间的日期。我的修改如下。
为了在绘制图表之前从 HTML 表中获取数据并使用它,我使用了 data.columns
属性(请参阅 http://api.highcharts.com/highcharts#data.columns)。
在声明图表选项之前,我编写了此代码来浏览 HTML 表并将内容添加到数组中。
// read through the HTML table and calculate cumulative effort
// solution inspired by:
// 1. http://stackoverflow.com/questions/3248869/how-do-i-get-data-from-a-data-table-in-javascript
// 2. http://stackoverflow.com/questions/10057226/how-to-get-html-table-td-cell-value-by-javascript
// set the series name as the default; this is the first entry read by data.columns
var seriesTime = ['Time'];
var seriesEffort = ['Effort'];
var seriesDuration = ['Duration'];
var table = document.getElementById('datatable');
var noRows = table.rows.length;
// go through the table and assign values to the series arrays
// start with the second row (r = 1) to omit the table's header
for (var r = 1; r < noRows; r++) {
seriesTime.push(Date.parse(table.rows[r].cells[0].innerHTML));
seriesEffort.push(parseInt(table.rows[r].cells[1].innerHTML));
seriesDuration.push(parseInt(table.rows[r].cells[2].innerHTML));
}
然后,我按如下方式使用这些数组:
data: {
// refer to demo link at: http://api.highcharts.com/highcharts#data.columns
columns: [
seriesTime, // categories
seriesEffort // first series
]
},
其工作方式是这些数组中预期的第一项是系列名称,这就是为什么我在首次声明数组时将默认值作为默认值的原因。
现在,一旦数据在数组中,您需要运行它们来计算累积总数并减去持续时间已过的数据。不幸的是,我在持续时间部分没有成功。这是我在小提琴中写的:
// next, go through the series arrays and tally up the cumulative totals based on duration
for (var t = 2; t < seriesTime.length; t++) {
seriesEffort[t]+=seriesEffort[t-1];
for (var e = 1; e < seriesEffort.length; e++) {
if (seriesTime[e] < seriesTime[t] - seriesDuration[t]) { // NOTE: this is where I'm getting stuck
seriesEffort[t]-=seriesEffort[e];
} else {
//seriesEffort[t]+=seriesEffort[e];
}
}
}
我希望这能让您更接近您的解决方案。很抱歉,我无法为您 100% 模拟这个。
我最终预处理了数据。首先,我将所有数据点累积到序列中。接下来,我用持续时间更新了日期时间 x 值。最后,我减去 x 值小于累积数据点的 x 值的每个单独的 y 值。