【问题标题】:Google charts floating min / max / average column chart谷歌图表浮动最小/最大/平均柱形图
【发布时间】:2014-01-18 17:11:05
【问题描述】:

我正在尝试创建如下所示的 Google 图表:

http://chart.googleapis.com/chart?cht=bvs&chs=200x125&chd=t2:10,50,60,80,40%7C50,60,100,40,20%7C30,70,90,95,45&chco=4d89f900,c6d9fd&chbh=20&chds=0,160&chm=H,336699,2,-1,1:22

基本上,我只想在一张图表上表示最大值、最小值和平均值,但我似乎不知道如何做到这一点。我知道可以在旧的基于 URL 的图表中使用标记,但它们已被弃用,而且新 API 似乎还不支持标记。

我尝试使用烛台,但我让它工作的唯一方法是在中间使用一条细线和一条水平线,因此它看起来像一堆加号,而不是带有线标记的浮动列。我知道我也可以在技术上将柱形图与阶梯式面积图堆叠在一起,但是这条线在所有条目中都是连续的,这是我不想要的。

谢谢。

编辑:使用 jmac 的方法和间隔,我想出了这个:

function drawVisualization() {
  // Create and populate the data table.
  var data = new google.visualization.DataTable();
  data.addColumn('string', 'label');
  data.addColumn('number', 'filler');
  data.addColumn('number', 'range');
  data.addColumn({type:'number', role:'interval'});
  data.addRows([
    ['A', 3, 4, 2],
    ['B', 2, 5, 4],
    ['C', 4, 4, 1],
    ['D', 5, 2, 1],
    ['E', 1, 8, 4],
  ]);

  // Create and draw the visualization.
  var ac = new google.visualization.ColumnChart(document.getElementById('visualization'));
  ac.draw(data, {
    width: 600,
    isStacked: true,
    series: [{color:'transparent'},{color:'silver'},{color:'silver'}],
    vAxis: {gridlines: {color: 'transparent'}, textPosition: 'none'},
    focusTarget: 'category',
    intervals: { 'style': 'bars', 'barWidth': 1.3, 'lineWidth': 2 },
  });
}

我还没有足够的声望来发布它的样子,但如果你把它贴在这里你可以看到它:https://code.google.com/apis/ajax/playground/?type=visualization#column_chart

此外,由于当您将鼠标悬停在填充区域上时它仍会突出显示填充区域,所以我发现了一个 css hack 来隐藏鼠标悬停时的突出显示:

#chart-div {
    svg g g g g rect {
      stroke-width:0px;
    }
}

【问题讨论】:

  • 查看Intervals 文档。这些示例都基于 LineChart,但它们可以与许多不同的图表类型一起使用。
  • 感谢您的回复,我尝试使用带有烛台图表的区间,但它们不起作用。如果我使用柱形图,它们会起作用,但是除非我在数据下方添加一个虚拟条目并匹配背景颜色,否则最小值和最大值不会“浮动”。柱形图 hack 仍然显示在图例中,并且该区域在悬停时突出显示,这是我不想要的。
  • 您可以通过设置series.<series index> 选项将其从图例中移除并使其消失,使其不会交互:{color: 'transparent', visibleInLegend: false, enableInteractivity: false}。我会用一个例子写一个答案。
  • 我想出了一个更好的方法,看答案。

标签: google-visualization


【解决方案1】:

您可以使用“盒子”样式的间隔来完成您想要的:

function drawChart () {
    var data = new google.visualization.DataTable();
    data.addColumn('string', 'Category');
    data.addColumn('number', 'Min');
    data.addColumn('number', 'Average');
    data.addColumn('number', 'Max');

    data.addRows([
        ['Foo', 3, 5, 7],
        ['Bar', 5, 8, 10],
        ['Baz', 0, 2, 6],
        ['Bat', 1, 2, 4]
    ]);

    var view = new google.visualization.DataView(data);
    // duplicate 1 column as a dummy data series, and add intervals to it
    view.setColumns([0, 1, {
        id: 'min',
        type: 'number',
        role: 'interval',
        calc: function (dt, row) {
            return dt.getValue(row, 1);
        }
    }, {
        id: 'avg',
        type: 'number',
        role: 'interval',
        calc: function (dt, row) {
            return dt.getValue(row, 2);
        }
    }, {
        id: 'max',
        type: 'number',
        role: 'interval',
        calc: function (dt, row) {
            return dt.getValue(row, 3);
        }
    }, 1, 2, 3]);

    var chart = new google.visualization.LineChart(document.querySelector('#chart_div'));
    chart.draw(view, {
        height: 400,
        width: 600,
        lineWidth: 0,
        intervals: {
            style: 'boxes'
        },
        legend: {
            position: 'none'
        },
        series: {
            0: {
                // dummy data series, controls color of intervals
                visibleInLegend: false,
                color: 'blue',
                enableInteractivity: false
            },
            1: {
                // min series options
            },
            2: {
                // average series options
            },
            3: {
                // max series options
            }
        }
    });
}
google.load('visualization', '1', {packages:['corechart'], callback: drawChart});

查看工作示例:http://jsfiddle.net/asgallant/pvJpx/

【讨论】:

  • 感谢您的详细回复!在我得到其他解决方案之前我没有看到它,但看起来这也可以正常工作。
  • 这是正确的答案。男孩忘记了间隔选项,我觉得很傻。
【解决方案2】:

如果你只关心它的视觉效果,你可以通过一些小技巧来重新创建它,让它看起来像这样:

这是代码:

function drawVisualization() {
  // Create and populate the data table.
  var data = google.visualization.arrayToDataTable([
    ['label', 'filler', 'bot half', 'top half'],
    ['A', 3, 2, 2],
    ['B', 2, 4, 1],
    ['C', 4, 1, 3],
    ['D', 5, 1, 1],
    ['E', 1, 4, 4],
  ]);

  // Create and draw the visualization.
  var ac = new google.visualization.ColumnChart(document.getElementById('visualization'));
  ac.draw(data, {
    width: 600,
    isStacked: true,
    series: [{color:'transparent'},{color:'silver'},{color:'silver'}],
    vAxis: {gridlines: {color: 'transparent'}, textPosition: 'none'},
    focusTarget: 'category',
  });
}

这是一个愚蠢的解决方法,但下面是给出min 值、max 值和avg 值的步骤:

  1. 创建一个等于min 的虚拟(透明)系列
  2. 为栏的下半部分创建第二个系列,等于avg - min
  3. 为栏的上半部分创建第三个系列,等于max - avg

虽然它看起来正确,但问题是与图表的交互会非常时髦,因为它不会向您显示您对图表的期望(您将有单独的未显示最小值、最大值和平均值的值,但仅显示上述点 2) 和 3) 大小的两个值)。你可以通过创造性地使用focusTarget 来解决这个问题,但这仍然会让你得到这样奇怪的东西:

现在您理论上可以重命名您的系列,并使用{v:, f:} 技巧使其看起来更好,这可能是一个很好的解决方法,但根据您的应用程序,它非常笨拙。如果你把这一切都搞定了,你会得到这样的:

这是通过以下代码完成的:

function drawVisualization() {
  // Create and populate the data table.
  var data = new google.visualization.DataTable();
  data.addColumn('string', 'Series Name');
  data.addColumn('number', 'Average');
  data.addColumn('number', 'Minimum');
  data.addColumn('number', 'Maximum');
  data.addRows([
    ['A', {v:3, f:'5'}, {v:2, f:'3'}, {v:2, f:'7'}],
    ['B', {v:2, f:'6'}, {v:4, f:'2'}, {v:1, f:'7'}],
    ['C', {v:4, f:'5'}, {v:1, f:'4'}, {v:3, f:'8'}],
    ['D', {v:5, f:'6'}, {v:1, f:'5'}, {v:1, f:'8'}],
    ['E', {v:1, f:'5'}, {v:4, f:'1'}, {v:4, f:'9'}],
  ]);

  // Create and draw the visualization.
  var ac = new google.visualization.ColumnChart(document.getElementById('visualization'));
  ac.draw(data, {
    width: 600,
    isStacked: true,
    series: [{color:'transparent'},{color:'silver'},{color:'silver'}],
    vAxis: {gridlines: {color: 'transparent'}, textPosition: 'none'},
    focusTarget: 'category',
  });
}

再一次,这很笨拙,并不完美(请参阅填充系列周围的灰色框,这无济于事),但它会显示信息,并且可以使用一些花哨的 javascript 和/或格式化程序自动执行数据视图取决于图表需要更改的频率以及您获取数据的格式。

【讨论】:

  • 感谢所有帮助!我用你的方法加上间隔让它工作了,这样分割平均线就更明显了。
  • @user,感谢您接受我的回答,但发布的其他解决方案效果更好,没有一些丑陋。我真的建议你尝试让那个工作(它像书面一样工作,看起来好多了)。
  • 我刚刚更改了任何人在未来最终会发现此问题的可接受答案。
猜你喜欢
  • 1970-01-01
  • 2015-12-22
  • 1970-01-01
  • 1970-01-01
  • 2017-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多