【问题标题】:Dynamically graph points with Highcharts使用 Highcharts 动态绘制点
【发布时间】:2016-11-13 19:05:16
【问题描述】:

如何动态绘制表格中的点?该表有两列专用于 x 和 y 坐标,另外还有一列用于持续时间。

示例

假设我有如下所示的表格。 Date 和 Effort 列将构成折线图的 x、y 坐标(时间戳、工作量)。此折线图将具有基于时间戳和工作量列的累积总数的数据点。 Duration 列将确定条目对折线图的数据点产生影响的时间。因此,基于此表,我想要一个折线图,其中包含数据点下列出的坐标。

时间戳      努力 持续时间
2016 年 4 月 13 日 12:13:12.15    10     100
2016 年 4 月 13 日 12:13:12.80    12     100
2016 年 4 月 13 日 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)

【问题讨论】:

    标签: graph highcharts


    【解决方案1】:

    其中一个 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% 的模型。

    【讨论】:

    • 感谢您的回答,但这并不是我想要的。您提供的示例依赖于您计算值并将它们输入到 td 中。就我而言,我希望从原始表中读取数据(使用“时间戳”、“努力”和“持续时间”列)并计算得到数据点。截至目前,我能想到如何以我想要的方式绘制表格的唯一方法是跟踪 x 轴,并在其持续时间完成后将表格中的每个值从累积总数中减去。你知道有没有办法做到这一点?
    • @ThanksInAdvance 啊,我明白你的意思了。是的,我相信有办法做到这一点。您用于从工作量和持续时间列中获取数据点的计算是什么?我很乐意相应地更新我的答案。
    • (4/13/2016 12:13:12.15, 10) 是第一个点,直接从表(第 1 行)中获取。 (4/13/2016 12:13:12.80, 22) 是第二点,因为我将第 1 行的 Effort 值添加到第 2 行的 Effort 值中,并且由于第 1 行的持续时间为 100 毫秒,因此它将继续被计入数据点的总努力值,直到它过期(在 12:13:13.15)。此时,将从累积的 Effort 值中减去第 1 行的 Effort 值。这种模式一直持续到完成。
    • @ThanksInAdvance 对于您的持续时间,100 是多少?那是 100 毫秒吗?
    • @ThanksInAdvance 我已经更新了上面的答案,提供了有关获取 HTML 表中的值并设置它们以进行计算的更多详细信息。不幸的是,我能够使累积总计部分起作用,但不能使持续时间的减法起作用。我希望这至少能让你更接近你的目标。
    【解决方案2】:

    我最终对数据进行了预处理。首先,我将所有数据点累积到系列中。接下来,我用持续时间更新了 datetime x 值。最后,我减去 x 值小于累积数据点 x 值的每个单独的 y 值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-23
      • 1970-01-01
      • 1970-01-01
      • 2022-01-06
      • 2017-07-25
      相关资源
      最近更新 更多