如何为谷歌折线图/谷歌折线图图例操作编写自己的自定义图例

IT技术 javascript charts google-visualization
2021-01-26 21:57:01

我正在使用 Google Visualization 为我的应用程序创建折线图。我有以下要求:

  1. 操作图例上的事件(比如 doubleClick,我已经以某种方式解决了)
  2. 将图例包装成两行,避免分页(大多数小鬼和必需的)

我已经完成了以下问题以获得我的答案的解决方案:1)图例分页问题(Google Interactive chart API) 问题:我会避免使用字体大小,因为图例的数量可能会随着时间的推移而增加

2)如何包装谷歌图表上的图例 问题:我不希望图例出现在位置:底部以外的任何地方。并且 maxLines 解决方案不适用于位置:底部

3)有什么办法可以避免在谷歌可视化图表的图例中分页,并在一个页面中以两行显示所有行? 问题:这是另一个链接,它提到了我的问题,但没有找到有用的答案。

4) Google 文档:标题:图表图例文本和样式 chdl、chdlp、chdls [所有图表] https://developers.google.com/chart/image/docs/chart_params#axis-label-styles-chxs 标题:设置图表边距 https://developers.google.com/chart/image/docs/chart_params#chart-margins-chma-all----charts 标题:工具提示 https://developers.google.com/chart/interactive/docs/ customizing_tooltip_content#tooltips-an-introduction 评论:这些是很少的谷歌文档链接,其中提到了很少的图例操作属性,但它们仍然没有解决我的问题。

5)https://github.com/google/google-visualization-issues/issues/1286 评论:这是我看到的链接,google没有提供很多操作图例的属性,也没有太多有用的信息来解决我的问题

6)谷歌图表图例操作 评论:这是唯一的链接,在那里我得到了关于如何解决我的问题的提示,即编写自己的图例。但是除了一个对我没有用的链接之外,没有为文档提供更多链接,没有 jsFiddle 或没有参考链接。

在经历了所有这些之后,我发现解决我的问题的唯一方法是编写我自己的自定义图例。但我不知道如何编写一个完整的元素添加到 google API。

请指导我完成这个,欢迎任何建议/链接/参考/提示。

谢谢你。

2个回答

示例:构建自定义图例,与数据和图表同步...

google.charts.load('44', {
  callback: drawChart,
  packages: ['controls', 'corechart']
});

function drawChart() {
  // adapted from a previous example
  var colorPallette = ['#273746','#707B7C','#dc7633','#f1c40f','#1e8449','#2874a6','#6c3483','#922b21'];

  var data = new google.visualization.DataTable();
  data.addColumn('date', 'X');
  data.addColumn('number', 'Y1');
  data.addColumn('number', 'Y2');

  data.addRow([new Date(2016,  0, 1),   1, 123]);
  data.addRow([new Date(2016,  1, 1),   6,  42]);
  data.addRow([new Date(2016,  2, 1),   4,  49]);
  data.addRow([new Date(2016,  3, 1),  23, 486]);
  data.addRow([new Date(2016,  4, 1),  89, 476]);
  data.addRow([new Date(2016,  5, 1),  46, 444]);
  data.addRow([new Date(2016,  6, 1), 178, 442]);
  data.addRow([new Date(2016,  7, 1),  12, 274]);
  data.addRow([new Date(2016,  8, 1), 123, 934]);
  data.addRow([new Date(2016,  9, 1), 144, 145]);
  data.addRow([new Date(2016, 10, 1), 135, 946]);
  data.addRow([new Date(2016, 11, 1), 178, 747]);

  // use view to add various columns for example purposes
  var view = new google.visualization.DataView(data);
  view.setColumns([0, 1, 2,
    {
      calc: function (data, row) {
        return data.getValue(row, 1) + data.getValue(row, 2);
      },
      type: 'number',
      label: 'Y3'
    },
    {
      calc: function (data, row) {
        return data.getValue(row, 2) - data.getValue(row, 1);
      },
      type: 'number',
      label: 'Y4'
    },
    {
      calc: function (data, row) {
        return data.getValue(row, 1) * 2;
      },
      type: 'number',
      label: 'Y5'
    },
    {
      calc: function (data, row) {
        return data.getValue(row, 2) * 3;
      },
      type: 'number',
      label: 'Y6'
    },
    {
      calc: function (data, row) {
        return data.getValue(row, 1) * 1.5;
      },
      type: 'number',
      label: 'Y7'
    },
    {
      calc: function (data, row) {
        return data.getValue(row, 1) * 1.5;
      },
      type: 'number',
      label: 'Y8'
    }
  ]);

  var control = new google.visualization.ControlWrapper({
    controlType: 'DateRangeFilter',
    containerId: 'control_div',
    options: {
      filterColumnIndex: 0
    }
  });

  var chart = new google.visualization.ChartWrapper({
    chartType: 'LineChart',
    containerId: 'chart_div',
    options: {
      chartArea: {
        width: '80%'
      },
      // add colors for legend mapping
      colors: colorPallette,
      hAxis: {
        format: 'MMM',
        slantedText: false,
        maxAlternation: 1
      },
      legend: 'none',
      width: 320
    }
  });

  // add legend marker
  function addLegendMarker(markerProps) {
    var legendMarker = document.getElementById('template-legend-marker').innerHTML;
    for (var handle in markerProps) {
      if (markerProps.hasOwnProperty(handle)) {
        legendMarker = legendMarker.replace('{{' + handle + '}}', markerProps[handle]);
      }
    }
    document.getElementById('legend_div').insertAdjacentHTML('beforeEnd', legendMarker);
  }

  // chart ready event
  google.visualization.events.addListener(chart, 'ready', function () {
    var legend = document.getElementById('legend_div');

    // colors from chart
    var colorPallette = chart.getOption('colors');

    // clear previous legend
    legend.innerHTML = '';

    // add legend marker for each Y axis column - skip X axis --> i = 1
    for (var i = 1; i < chart.getDataTable().getNumberOfColumns(); i++) {
      var markerProps = {};
      markerProps.index = i;
      markerProps.color = colorPallette[i - 1];
      markerProps.label = chart.getDataTable().getColumnLabel(i);
      addLegendMarker(markerProps);
    }

    // add click event to each legend marker
    var markers = legend.getElementsByTagName('DIV');
    Array.prototype.forEach.call(markers, function(marker) {
      marker.addEventListener('click', function (e) {
        var marker = e.target || e.srcElement;
        if (marker.tagName.toUpperCase() !== 'DIV') {
          marker = marker.parentNode;
        }
        var columnIndex = parseInt(marker.getAttribute('data-columnIndex'));
        document.getElementById('message_div').innerHTML = 'legend marker clicked = ' + chart.getDataTable().getColumnLabel(columnIndex);
      }, false);
    });
  });

  var dash = new google.visualization.Dashboard(document.getElementById('dashboard'));
  dash.bind([control], [chart]);
  dash.draw(view);
}
#legend_div {
  text-align: center;
  width: 320px;
}

.legend-marker {
  display: inline-block;
  padding: 16px 4px 8px 4px;
}

.legend-marker-color {
  display: inline-block;
  height: 12px;
  width: 12px;
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="dashboard">
  <div id="chart_div"></div>
  <div id="legend_div"></div>
  <br/>
  <div id="control_div"></div>
  <br/>
  <div id="message_div"></div>
</div>

<!-- template for building marker -->
<script id="template-legend-marker" type="text/html">
  <div class="legend-marker" data-columnIndex="{{index}}">
    <div class="legend-marker-color" style="background-color: {{color}}"></div>
    <span>{{label}}</span>
  </div>
</script>

上面的例子很有帮助,谢谢。提醒一下 - 如果将此代码与 Python Jinja 模板一起使用,由于此处使用了 {{ }},代码片段将不起作用。jinja 模板将使用空字符串或它可能为这些标记保存的值替换 template-legend-marker 中的标记。
2021-03-14 21:57:01
感谢您的代码片段......它解释得很好......现在我开始开发我自己的,一旦我完成,我将用答案更新我的问题......你的答案将帮助我直接解决问题。
2021-03-23 21:57:01
 if ($("#source svg text[text-anchor='end']").length > 0){
        var n = $("#source svg text[text-anchor='end']").length;
        $("#source svg text[text-anchor='end']")[n-5].innerHTML = "";
        $("#source svg text[text-anchor='end']")[n-4].innerHTML = "Create your own legend";
        $("#source svg text[text-anchor='end']")[n-3].innerHTML = "Create your own legend";
        $("#source svg text[text-anchor='end']")[n-2].innerHTML = "Create your own legend";
        $("#source svg text[text-anchor='end']")[n-1].innerHTML = "";
    }
纯代码答案在 StackOverflow 上的value很低,因为它们在教育 OP 和成千上万未来的研究人员方面做得很差。请花时间编辑您的答案并解释您的方法是如何工作的以及为什么推荐它。工作解决方案是任何答案的良好开端,但始终以教育为目的发布答案。
2021-03-31 21:57:01