Google可视化集群具有目标线的多个列堆栈 [英] Google Visualization cluster multiple column stacks having goal lines

查看:52
本文介绍了Google可视化集群具有目标线的多个列堆栈的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标是将两个或更多具有相应目标线的列堆栈聚类.

My goal is to cluster two or more column stacks having corresponding goal lines.

获取此图表的最佳方法是什么?

What is the best way to get this chart?

我最初的想法是使用 ComboChart .我只能用多行完成一个堆栈栏.

My initial thought was to use a ComboChart. I can only accomplish a single stack bar with multiple lines.

我能够尝试使用条形图"类型图表(如以下代码片段),并使用两个轴完成了两个群集的条形图堆栈,但无法获取线.我还认为,将来这可能会限制为只有两个堆栈.

I was able to try a 'bar' type chart (below snippet) and accomplished two clustered bar stacks using two axis but cannot get lines. I also think this could be limiting in the future to only two stacks.

有什么想法吗?一如既往的感谢!

Any ideas?? Thanks as always!

google.setOnLoadCallback(drawChart);

      function drawChart() {
        var data = google.visualization.arrayToDataTable([
          ['Year', 'Sales', 'Expenses', 'Goal Line 1', 'Profit', 'Bonus', 'Goal Line 2'],
          ['2014', 1000, 400, 400, 200, 50, 500],
          ['2015', 1170, 460, 400, 250, 2000, 500],
          ['2016', 660, 1120, 400, 300, 10, 500],
          ['2017', 1030, 540, 400, 350, 15, 500]
        ]);

        var options = {

          bars: 'vertical',
          isStacked: true,
          series: {
            0: { targetAxisIndex: 1 },
            1: { targetAxisIndex: 1 },
            2: { targetAxisIndex: 1 }, //this should be a line 
            3: { targetAxisIndex: 2 },
            4: { targetAxisIndex: 2 },
            5: { targetAxisIndex: 2 } //this should be a line 
          },
          vAxes: {

          },

          height: 400,
          xcolors: ['#1b9e77', '#d95f02', '#7570b3']
        };

        var chart = new google.charts.Bar(document.getElementById('chart_div'));

        chart.draw(data, google.charts.Bar.convertOptions(options));


      }

<script type="text/javascript" src="https://www.google.com/jsapi?autoload={'modules':[{'name':'visualization','version':'1.1','packages':['bar']}]}"></script>
       <div id="chart_div"></div>
    <br/>

============更新============
因此,我现在尝试了一个具有两个轴的ColumnChart.我可以看到我现在得到了两个堆栈,但它们在另一个堆栈的前面.您可以看到红色/橙色堆栈从蓝色/紫色堆栈后面伸出.

============UPDATE=============
So I've tried now a ColumnChart with two axis. I can see that I get two stacks now but they are one in front of the other. You can see that the red/orange stack sticks out from behind the blue/purple stack.

是否可以将堆栈1向左偏移,将堆栈2向右偏移?然后我认为图表可以在我的应用程序中正常工作.

Is it possible to offset stack 1 to the left and stack 2 to the right? Then I think visually the chart could work for my application.

      google.charts.load('current', {
        'packages': ['corechart']
      });
      google.charts.setOnLoadCallback(drawVisualization);

      function drawVisualization() {
        // Some raw data (not necessarily accurate)
        var data = google.visualization.arrayToDataTable([
          ['Month', 'Ax1 line', 'Stack1 1', 'Stack1 2', 'Ax2 line', 'Stack2 1', 'Stack2 2'],
          ['2004/05', 10, 110, 210, 710, 810, 910],
          ['2005/06', 20, 120, 220, 720, 820, 920],
          ['2006/07', 30, 130, 230, 730, 830, 930],
          ['2007/08', 40, 140, 240, 740, 840, 940],
          ['2008/09', 50, 150, 250, 750, 850, 950]
        ]);

        var options = {
          title: 'Monthly Coffee Production by Country',
          vAxis: {
            title: 'Cups'
          },
          hAxis: {
            title: 'Month'
          },
          seriesType: 'bars',
          series: {
            0: { type: 'line', targetAxisIndex: 1},
            1: { type: 'bars', targetAxisIndex: 1},
          	2: { type: 'bars', targetAxisIndex: 1},
            3: { type: 'line', targetAxisIndex: 2},   
            4: { type: 'bars', targetAxisIndex: 2},  
            5: { type: 'bars', targetAxisIndex: 2}
          },
          isStacked: true
        };

        var chart = new google.visualization.ComboChart(document.getElementById('chart_div'));
        chart.draw(data, options);
      }

<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
       <div id="chart_div" style="width: 900px; height: 500px;"></div>
   

推荐答案

这里的问题是 material 图表不支持组合图表(添加行).
经典图表不支持多个堆栈.

the problem here, material charts do not support combo charts (adding the line).
and classic charts do not support multiple stacks.

但是,通过在列系列之间添加线系列,
并将一个移动到另一个y轴,
堆栈会彼此分开,但会分开.

however, by adding a line series in between the columns series,
and moving one to another y-axis,
the stacks will become separated, though on top of one another.

在图表的'ready'事件中,我们可以将两个堆栈的大小减小一半,
然后将第二个堆栈移到右侧.

on the chart's 'ready' event, we can reduce the size of both stacks by half,
then move the second stack to the right.

这里最大的问题是互动性.
图表会将所有列重置为互动时的原始位置(例如,悬停).
因此,我们必须使用 MutationObserver 来防止重置.

the biggest problem here is on interactivity.
the chart will reset all the columns back to their original position on interactivity, such as hover.
as such, we must use a MutationObserver to prevent the reset.

但是,还有一些我尚未解决的小问题.

however, there is still a couple minor issues I haven't worked out.

当您将鼠标悬停在第一个堆栈上时,工具提示会出现在原始位置的上方.
并且在原始位置周围有一个亮点.

when you hover the first stack, the tooltip appears above the original position.
and there is a highlight surrounding the original position.

这是我到目前为止所拥有的...

here is what I have so far...

google.charts.load('current', {
  packages: ['corechart']
}).then(function () {
  var data = google.visualization.arrayToDataTable([
    ['Month', 'Ax1 line', 'Stack1 1', 'Stack1 2', 'Ax2 line', 'Stack2 1', 'Stack2 2'],
    ['2004/05', 10, 110, 210, 710, 810, 910],
    ['2005/06', 20, 120, 220, 720, 820, 920],
    ['2006/07', 30, 130, 230, 730, 830, 930],
    ['2007/08', 40, 140, 240, 740, 840, 940],
    ['2008/09', 50, 150, 250, 750, 850, 950]
  ]);

  var options = {
    title: 'Monthly Coffee Production by Country',
    vAxis: {
      title: 'Cups'
    },
    hAxis: {
      title: 'Month'
    },
    seriesType: 'bars',
    series: {
      0: { type: 'line', targetAxisIndex: 0},
      1: { type: 'bars', targetAxisIndex: 0},
      2: { type: 'bars', targetAxisIndex: 0},
      3: { type: 'line', targetAxisIndex: 1},
      4: { type: 'bars', targetAxisIndex: 1},
      5: { type: 'bars', targetAxisIndex: 1}
    },
    isStacked: true,
    legend: {
      maxLines: 2,
      position: 'top'
    },
    tooltip: {
      target: 'both'
    }
  };

  var chart = new google.visualization.ComboChart(document.getElementById('chart_div'));
  var chartLayout;
  var chartBounds;
  var legendColors = [];
  var saveCoords = {};
  google.visualization.events.addListener(chart, 'ready', function () {
    // init chart elements
    chartLayout = chart.getChartLayoutInterface();
    chartBounds = chartLayout.getChartAreaBoundingBox();
    var bars = chart.getContainer().getElementsByTagName('rect');

    // find legend markers
    Array.prototype.forEach.call(bars, function (bar) {
      var color = bar.getAttribute('fill');
      var xCoord = parseFloat(bar.getAttribute('x'));
      var yCoord = parseFloat(bar.getAttribute('y'));
      if ((xCoord >= chartBounds.left) && (yCoord < chartBounds.top) && (color !== '#ffffff')) {
        legendColors.push(color);
      }
    });

    // find bars
    Array.prototype.forEach.call(bars, function (bar, index) {
      var xCoord = parseFloat(bar.getAttribute('x'));
      var yCoord = parseFloat(bar.getAttribute('y'));
      if ((xCoord > chartBounds.left) && (yCoord > chartBounds.top)) {
        var color = bar.getAttribute('fill');
        var width = parseFloat(bar.getAttribute('width')) / 2;
        bar.setAttribute('width', width);
        saveCoords[xCoord + yCoord] = {
          width: width,
          x: xCoord
        };
        if (legendColors.indexOf(color) > 1) {
          bar.setAttribute('x', xCoord + width);
          saveCoords[xCoord + yCoord].x = xCoord + width;
          saveCoords[xCoord + width + yCoord] = saveCoords[xCoord + yCoord];
        }
      }
    });

    var observer = new MutationObserver(function () {
      // reset bars
      var bars = chart.getContainer().getElementsByTagName('rect');
      Array.prototype.forEach.call(bars, function (bar, index) {
        var xCoord = parseFloat(bar.getAttribute('x'));
        var yCoord = parseFloat(bar.getAttribute('y'));
        if ((xCoord > chartBounds.left) && (yCoord > chartBounds.top)) {
          var color = bar.getAttribute('fill');
          if (saveCoords.hasOwnProperty(xCoord + yCoord)) {
            bar.setAttribute('width', saveCoords[xCoord + yCoord].width);
            bar.setAttribute('x', saveCoords[xCoord + yCoord].x);
          }
        }
      });
    });
    observer.observe(chart.getContainer(), {
      childList: true,
      subtree: true
    });
  });

  chart.draw(data, options);
  window.addEventListener('resize', function () {
    chart.draw(data, options);
  });
});

#chart_div {
  height: 400px;
}

<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

注意:我也发现了一个曾经在这里发布的问题.目前,图例必须完全显示在一行上.要在此处运行示例,您必须运行代码段,然后点击整页.

Note: I also found an issue once posted here. For now, the legend must be fully displayed on one line. To run the example here, you must run the snippet, then click Full page.

这篇关于Google可视化集群具有目标线的多个列堆栈的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆