在 Highcharts 底部配置数据 Table

Configure Data Table at bottom in Highcharts

我们将 Higcharts 库用于我们的图表,并希望在图表下方的 table 中淡入和淡出数据。我找到了一些代码部分来定义 table 在 javaScript 本身中的数据外观,但在一些配置方面遇到了困难,如定义:

因为我的 javaScript-技能相当有限。

这里是我的例子:https://jsfiddle.net/BlackLabel/bs12atdq/

var H = Highcharts,
  {
    pick,
    fireEvent
  } = H,
  htmlencode = function(html) {
    return html
      .replace(/&/g, '&')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#x27;')
      .replace(/\//g, '&#x2F;');
  }

H.Chart.prototype.getTable = function(useLocalDecimalPoint) {
  var html = '<table id="highcharts-data-table-' + this.index + '">',
    options = this.options,
    decimalPoint = useLocalDecimalPoint ? (1.1).toLocaleString()[1] : '.',
    useMultiLevelHeaders = pick(options.exporting.useMultiLevelHeaders, true),
    rows = this.getDataRows(useMultiLevelHeaders),
    rowLength = 0,
    topHeaders = useMultiLevelHeaders ? rows.shift() : null,
    subHeaders = rows.shift(),
    // Compare two rows for equality
    isRowEqual = function(row1, row2) {
      var i = row1.length;
      if (row2.length === i) {
        while (i--) {
          if (row1[i] !== row2[i]) {
            return false;
          }
        }
      } else {
        return false;
      }
      return true;
    },
    // Get table cell HTML from value
    getCellHTMLFromValue = function(tag, classes, attrs, value) {
      var val = pick(value, ''),
        className = 'text' + (classes ? ' ' + classes : '');
      // Convert to string if number
      if (typeof val === 'number') {






        //-------------------------------------------------------
        val = H.numberFormat(val, null, null, ',');
        //-------------------------------------------------------








        val = val.toString();
        if (decimalPoint === ',') {
          val = val.replace('.', decimalPoint);
        }
        className = 'number';
      } else if (!value) {
        className = 'empty';
      }

      return '<' + tag + (attrs ? ' ' + attrs : '') +
        ' class="' + className + '">' +
        val + '</' + tag + '>';
    },
    // Get table header markup from row data
    getTableHeaderHTML = function(topheaders, subheaders, rowLength) {
      var html = '<thead>',
        i = 0,
        len = rowLength || subheaders && subheaders.length,
        next,
        cur,
        curColspan = 0,
        rowspan;
      // Clean up multiple table headers. Chart.getDataRows() returns two
      // levels of headers when using multilevel, not merged. We need to
      // merge identical headers, remove redundant headers, and keep it
      // all marked up nicely.
      if (useMultiLevelHeaders &&
        topheaders &&
        subheaders &&
        !isRowEqual(topheaders, subheaders)) {
        html += '<tr>';
        for (; i < len; ++i) {
          cur = topheaders[i];
          next = topheaders[i + 1];
          if (cur === next) {
            ++curColspan;
          } else if (curColspan) {
            // Ended colspan
            // Add cur to HTML with colspan.
            html += getCellHTMLFromValue('th', 'highcharts-table-topheading', 'scope="col" ' +
              'colspan="' + (curColspan + 1) + '"', cur);
            curColspan = 0;
          } else {
            // Cur is standalone. If it is same as sublevel,
            // remove sublevel and add just toplevel.
            if (cur === subheaders[i]) {
              if (options.exporting.useRowspanHeaders) {
                rowspan = 2;
                delete subheaders[i];
              } else {
                rowspan = 1;
                subheaders[i] = '';
              }
            } else {
              rowspan = 1;
            }
            html += getCellHTMLFromValue('th', 'highcharts-table-topheading', 'scope="col"' +
              (rowspan > 1 ?
                ' valign="top" rowspan="' + rowspan + '"' :
                ''), cur);
          }
        }
        html += '</tr>';
      }
      // Add the subheaders (the only headers if not using multilevels)
      if (subheaders) {
        html += '<tr>';
        for (i = 0, len = subheaders.length; i < len; ++i) {
          if (typeof subheaders[i] !== 'undefined') {
            html += getCellHTMLFromValue('th', null, 'scope="col"', subheaders[i]);
          }
        }
        html += '</tr>';
      }
      html += '</thead>';
      return html;
    };

  // Find longest row
  for (var i = 0, len = rows.length; i < len; ++i) {
    if (rows[i].length > rowLength) {
      rowLength = rows[i].length;
    }
  }
  // Add header
  html += getTableHeaderHTML(topHeaders, subHeaders, Math.max(rowLength, subHeaders.length));
  // Transform the rows to HTML
  html += '<tbody>';
  rows.forEach(function(row) {
    html += '<tr>';
    for (var j = 0; j < rowLength; j++) {
      // Make first column a header too. Especially important for
      // category axes, but also might make sense for datetime? Should
      // await user feedback on this.
      html += getCellHTMLFromValue(j ? 'td' : 'th', null, j ? '' : 'scope="row"', row[j]);
    }
    html += '</tr>';
  });
  html += '</tbody></table>';
  var e = {
    html: html
  };
  fireEvent(this, 'afterGetTable', e);
  return e.html;
};


$(document).ready(function() {
  var chart = {
    type: 'line'
  };

  var plotOptions = {
    line: {
      marker: {
        enabled: false
      }
    }
  };


  var title = {
    text: 'title',
    style: {
      fontSize: '18px'
    },
    align: 'left'
  };
  var subtitle = {
    text: 'subtitle',
    style: {
      fontSize: '12px'
    },
    align: 'left'
  };

  var yAxis = {
    gridLineWidth: 0,
    plotLines: [{
      color: "#ccd6eb",
      value: 0,
      width: 2
    }],
    lineWidth: 1,
    title: ''
  };

  var xAxis = {
    categories: [2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020],
    rotation: -90,
    align: 'left'
  };

  var legend = {
    layout: 'horizontal',
    align: 'center',
    verticalAlign: 'bottom',
    padding: 25,
    symbolPadding: 10,
    symbolWidth: 25,
    margin: -10,
    itemStyle: {
      fontWeight: 'normal'
    }
  };

  var tooltip = {
    pointFormat: '{series.name}: <b>{point.y:,.1f} %',
    shared: false
  };

  var series = [{
    name: 'Group 1',
    color: '#3CA433',
    data: [-0.9, -0.7, -0.4, 0.2, 0.2, 0.5, 0.7, 0.5, 0.9, 0.8, 1.0]
  }, {
    name: 'Group 2',
    color: '#0064e6',
    data: [1.4, 1.7, 1.8, 1.5, 1.4, 1.1, 1.0, 0.8, 0.5, 0.7, 0.7]
  }, {
    name: 'Group 3',
    color: '#27408B',
    data: [2.8, 3.3, 3.3, 3.0, 3.2, 3.2, 2.6, 3.0, 3.0, 3.1, 3.1]
  }];


  var credits = {
    text: 'Source',
    href: false,
    style: {
      color: '#999999',
      cursor: false,
      fontSize: '10px'
    },
    position: {
      align: 'left',
      x: 10,
      y: -20
    }
  };
  var exporting = {
    allowHTML: true,
    enabled: true,
    showTable: true,
    filename: 'Linechart_Example',
    buttons: {
      contextButton: {
        menuItems: "printChart separator downloadPNG downloadJPEG downloadSVG separator downloadXLS".split(" ")
      }
    },
    /*csv: {
        columnHeaderFormatter: function (item) {
            if(item instanceof Highcharts.Axis) {
                return 'Quartal';
            } else {
                if(item instanceof Highcharts.Series) {
                    return item.name;
                }
            }
        }
    }*/
  };

  var highchartsOptions = Highcharts.setOptions({
    lang: {
      decimalPoint: '.',
      thousandsSep: "'",
      months: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
      weekdays: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
      shortMonths: ['Jan', 'Feb', 'Mrz', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
      contextButtonTitle: 'Drucken, Download, Export',
      downloadJPEG: 'Download JPEG Bild',
      downloadPNG: 'Download PNG Bild',
      downloadSVG: 'Download SVG Vektor Bild',
      downloadXLS: 'Download XLS',
      printChart: 'Bild drucken',
      viewData: 'Datentabelle ein-/ausblenden',
      resetZoom: "Zoom zurücksetzen",
      resetZoomTitle: "Zoom zurücksetzen",
      drillUpText: "Zurück"
    }
  });

  var json = {};
  json.chart = chart;
  json.title = title;
  json.subtitle = subtitle;
  json.yAxis = yAxis;
  json.xAxis = xAxis;
  json.series = series;
  json.tooltip = tooltip;
  json.legend = legend;
  json.credits = credits;
  json.exporting = exporting;
  json.plotOptions = plotOptions;
  json.highchartsOptions = highchartsOptions;

  $('#Linechart_Example').highcharts(json);
}); ```

Thanks for any help. 
  1. 要编辑小数位数,请更改 numberFormat 方法中的参数。

    val = H.numberFormat(val, null, null, ',');
    
  2. font-weight: normal 样式添加到创建的 th 标签。

     for (i = 0, len = subheaders.length; i < len; ++i) {
       if (typeof subheaders[i] !== 'undefined') {
         html += getCellHTMLFromValue('th', null, 'scope="col"' + ' style="font-weight: normal;"', subheaders[i]);
       }
     }
    

现场演示: https://jsfiddle.net/BlackLabel/1k4L5gd8/

API参考:https://api.highcharts.com/class-reference/Highcharts#.numberFormat