如何更改高图中条形的宽度?

时间:2012-10-24 21:38:58

标签: javascript highcharts

使用类似this one的条形图,可以更改条形的宽度以表示另一个数据属性,例如水果的重量。水果越重,酒吧越厚。

您使用脚本here。我对其他javascript绘图库开放,只要它们是免费的,就可以这样做。

$(function () {
    var chart;
    $(document).ready(function() {
        chart = new Highcharts.Chart({
            chart: {
                renderTo: 'container',
                type: 'column'
            },
            title: {
                text: 'Column chart with negative values'
            },
            xAxis: {
                categories: ['Apples', 'Oranges', 'Pears', 'Grapes', 'Bananas']
            },
            tooltip: {
                formatter: function() {
                    return ''+
                        this.series.name +': '+ this.y +'';
                }
            },
            credits: {
                enabled: false
            },
            series: [{
                name: 'John',
                data: [5, 3, 4, 7, 2]
                // I would like something like this (3.5, 6 etc is the width) :
                // data: [[5, 3.4], [3, 6], [4, 3.4], [7, 2], [2, 5]]
            }, {
                name: 'Jane',
                data: [2, -2, -3, 2, 1]
            }, {
                name: 'Joe',
                data: [3, 4, 4, -2, 5]
            }]
        });
    });

});​

4 个答案:

答案 0 :(得分:25)



pointWidth是设置条形宽度所需的。试试

plotOptions: {
            series: {
                pointWidth: 15
            }
        }


此显示条宽度为15px。玩here。刚刚对现有代码进行了编辑。

答案 1 :(得分:8)

我使用一组面积图来模拟可变宽度列/条形图。比如说,每个栏/栏都由一个矩形区域表示。

请参阅我的小提琴演示(http://jsfiddle.net/calfzhou/TUt2U/)。

$(function () {
    var rawData = [
        { name: 'A', x: 5.2, y: 5.6 },
        { name: 'B', x: 3.9, y: 10.1 },
        { name: 'C', x: 11.5, y: 1.2 },
        { name: 'D', x: 2.4, y: 17.8 },
        { name: 'E', x: 8.1, y: 8.4 }
    ];

    function makeSeries(listOfData) {
        var sumX = 0.0;
        for (var i = 0; i < listOfData.length; i++) {
            sumX += listOfData[i].x;
        }
        var gap = sumX / rawData.length * 0.2;
        var allSeries = []
        var x = 0.0;
        for (var i = 0; i < listOfData.length; i++) {
            var data = listOfData[i];
            allSeries[i] = {
                name: data.name,
                data: [
                    [x, 0], [x, data.y],
                    {
                        x: x + data.x / 2.0,
                        y: data.y,
                        dataLabels: { enabled: true, format: data.x + ' x {y}' }
                    },
                    [x + data.x, data.y], [x + data.x, 0]
                ],
                w: data.x,
                h: data.y
            };
            x += data.x + gap;
        }
        return allSeries;
    }

    $('#container').highcharts({
        chart: { type: 'area' },
        xAxis: {
            tickLength: 0,
            labels: { enabled: false}
        },
        yAxis: {
            title: { enabled: false}
        },
        plotOptions: {
            area: {
                marker: {
                    enabled: false,
                    states: {
                        hover: { enabled: false }
                    }
                }
            }
        },
        tooltip: {
            followPointer: true,
            useHTML: true,
            headerFormat: '<span style="color: {series.color}">{series.name}</span>: ',
            pointFormat: '<span>{series.options.w} x {series.options.h}</span>'
        },
        series: makeSeries(rawData)
    });
});

my demo chart

答案 2 :(得分:1)

如果你拥有获得更优的Marimekko图表的许可证,那么Fusioncharts可能是最好的选择......

我已经做了一些尝试在高图中获得Marimekko图表解决方案的工作。它并不完美,但近似于Fusion Charts页面上的第一个Marimekko图表示例......

http://www.fusioncharts.com/resources/chart-tutorials/understanding-the-marimekko-chart/

关键是使用dateTime轴,因为该模式为您在X轴上分布点和线的方式提供了更大的灵活性,这使您能够在此轴上构建可变大小的“条形” 。我使用0-1000秒的空间,在图表外部计算出这个比例的映射,以近似百分比值来调整垂直线。这里(http://jsfiddle.net/miken/598d9/2/)是一个创建可变宽度柱形图的jsfiddle示例。

    $(function () {

    var chart;
        Highcharts.setOptions({
            colors: [ '#75FFFF', '#55CCDD', '#60DD60' ]
        });
        $(document).ready(function() {
            var CATEGORY = {  // number out of 1000
            0: '',    
            475: 'Desktops',
            763: 'Laptops',
            1000: 'Tablets'  
        };
        var BucketSize = {  
            0: 475,
            475: 475,
            763: 288,
            1000: 237   
        };
        chart = new Highcharts.Chart({
            chart: {
                renderTo: 'container',
                type: 'area'
            },
            title: {
                text: 'Contribution to Overall Sales by Brand & Category (in US$)<br>(2011-12)'
            },
            xAxis: {
                min: 0,
                max: 1000,
                title: {
                    text: '<b>CATEGORY</b>'
                },
                tickInterval: 1,
                minTickInterval: 1,
                dateTimeLabelFormats: {
                    month: '%b'
                },
                labels: {
                    rotation: -60,
                    align: 'right',
                    formatter: function() {
                        if (CATEGORY[this.value] !== undefined) {
                            return '<b>' + CATEGORY[this.value] + ' (' + 
                                this.value/10 + '%)</b>';
                        }
                    }
                }
            },
            yAxis: {
                max: 100,
                gridLineWidth: 0,
                title: {
                    text: '<b>% Share</b>'
                },
                labels: {
                    formatter: function() {
                        return this.value +'%'
                    }
                }
            },
            tooltip: {
                shared: true,
                useHTML: true,
                formatter: function () {
                    var result = 'CATEGORY: <b>' +
                        CATEGORY[this.x] + ' (' + Highcharts.numberFormat(BucketSize[this.x]/10,1) + '% sized bucket)</b><br>';
                    $.each(this.points, function(i, datum) {
                        if (datum.point.y !== 0) {
                            result += '<span style="color:' +
                                datum.series.color + '"><b>' +
                                datum.series.name + '</b></span>: ' +
                                    '<b>$' + datum.point.y + 'K</b> (' +
                                Highcharts.numberFormat(
                                    datum.point.percentage,2) +
                                '%)<br/>';
                        }
                    });
                return (result);
                }
            },
            plotOptions: {
                area: {
                    stacking: 'percent',
                    lineColor: 'black',
                    lineWidth: 1,
                    marker: {
                        enabled: false
                    },
                    step: true
                }
            },
            legend: {
                layout: 'vertical',
                align: 'right',
                verticalAlign: 'top',
                x: 0,
                y: 100,
                borderWidth: 1,
                title: {
                text : 'Brand:'
                }
            },
            series: [ {
                name: 'HP',
                data: [
                    [0,298],
                    [475,109],
                    [763,153],
                    [1000,153]          
                ]
            }, {
               name: 'Dell',
                data: [
                    [0,245],
                    [475,198],
                    [763,120],
                    [1000,120]
               ]
            }, {
                name: 'Sony',
                data: [
                    [0,335],
                    [475,225],
                    [763,164],
                    [1000,164]          
               ]
            }]
        },
        function(chart){    
            // Render bottom line.
            chart.renderer.path(['M', chart.plotLeft, chart.plotHeight + 66, 'L', chart.plotLeft+chart.plotWidth, chart.plotHeight + 66])
            .attr({
                'stroke-width': 3,
                stroke: 'black',
                zIndex:50
            })
            .add();
            for (var category_idx in CATEGORY) {
                chart.renderer.path(['M', (Math.round((category_idx / 1000) * chart.plotWidth)) + chart.plotLeft, 66, 'V', chart.plotTop + chart.plotHeight])
                .attr({
                    'stroke-width': 1,
                    stroke: 'black',
                    zIndex:4
                })
                .add();
            }
        });
    });
});

它添加了一个额外的数组,允许您将类别名称映射到第二个tic值,以便为您提供您可能需要的更多“类别”视图。我还在底部添加了代码,在不同的列和图表的底线之间添加垂直分隔线。它可能需要对周围标签的大小进行一些调整等,我在这里作为数学的一部分用像素硬编码,但它应该是可行的。

使用'百分比'类型重音可让您使用y比例计算原始数据中的百分比总和,而如上所述,您需要对x轴进行自己的数学运算。我更依赖于工具提示功能来提供标签等,而不是图表本身的标签。

这项工作的另一个重大改进是找到一种方法,使工具提示悬停区域和标签聚焦并居中并包含条形本身,而不是现在每个条形的右边框。如果有人想添加,请随意到这里。

答案 3 :(得分:0)

如果我做对了,您希望每个条形都具有不同的宽度。我遇到了同样的问题,为找到提供此选项的库付出了很多努力。我得出了结论-没有。

无论如何,我都玩了一些高级图表,变得很有创意,并提出了以下建议:
您提到您希望数据看起来像这样:data: [[5, 3.4], [3, 6], [4, 3.4]],第一个值是高度,第二个值是宽度。

让我们使用highcharts的柱状图来完成它。

第1步:
为了更好地区分条形图,请将每个条形图输入为新系列。由于我是动态生成数据的,因此必须动态分配新系列:

const objects: any = [];
const extra = this.data.length - 1;
this.data.map((range) => {
  const obj = {
    type: 'column',
    showInLegend: false,
    data: [range[1]],
    animation: true,
    borderColor: 'black',
    borderWidth: 1,
    color: 'blue'
  };
  for (let i = 0; i < extra; i++) {
    obj.data.push(null);
  }
  objects.push(obj);
});
this.chartOptions.series = objects;

这样,您的不同系列将如下所示:

series: [{
  type: 'column',
  data: [5, 3.4]
}, {
  type: 'column',
  data: [3, 6]
}, {
  type: 'column',
  data: [4, 3.4]
}]



第2步:
将其分配为高图的绘图选项:

plotOptions: {
  column: {
    pointPadding: 0,
      borderWidth: 0,
      groupPadding: 0,
      shadow: false
  }
}



第3步:
现在,让我们发挥创造力-为所有条形设定相同的起点,我们需要将每个条形图移至图形的起点:

setColumnsToZero() {
  this.data.map((item, index) => {
    document.querySelector('.highcharts-series-' + index).children[0].setAttribute('x', '0');
  });
}



第4步:

getDistribution() {
  let total = 0;

  // Array including all of the bar's data: [[5, 3.4], [3, 6], [4, 3.4]]
  this.data.map(item => {
    total = total + item[0];
  });

  // MARK: Get xAxis' total width
  const totalWidth = document.querySelector('.highcharts-axis-line').getBoundingClientRect().width;

  let pos = 0;
  this.data.map((item, index) => {
    const start = item[0];
    const width = (start * totalWidth) / total;
    document.querySelector('.highcharts-series-' + index).children[0].setAttribute('width', width.toString());
    document.querySelector('.highcharts-series-' + index).children[0].setAttribute('x', pos.toString());
    pos = pos + width;
    this.getPointsPosition(index, totalWidth, total);
  });
}



第4步:
让我们到达xAxis的要点。在第一个功能中,修改已经存在的点,将最后一个点移到轴的末端,然后隐藏其他点。在第二个函数中,我们克隆最后一个点,将其修改为总共6个或3个xAxis点,然后将每个点移动到正确的位置

getPointsPosition(index, totalWidth, total) {
  const col = document.querySelector('.highcharts-series-' + index).children[0];
  const point = (document.querySelector('.highcharts-xaxis-labels').children[index] as HTMLElement);
  const difference = col.getBoundingClientRect().right - point.getBoundingClientRect().right;
  const half = point.getBoundingClientRect().width / 2;
  if (index === this.data.length - 1) {
    this.cloneNode(point, difference, totalWidth, total);
  } else {
    point.style.display = 'none';
  }
  point.style.transform = 'translateX(' + (+difference + +half) + 'px)';

  point.innerHTML = total.toString();
}

cloneNode(ref: HTMLElement, difference, totalWidth, total) {
  const width = document.documentElement.getBoundingClientRect().width;

  const q = total / (width > 1000 && ? 6 : 3);
  const w = totalWidth / (width > 1000 ? 6 : 3);
  let val = total;
  let valW = 0;
  for (let i = 0; i < (width > 1000 ? 6 : 3); i++) {
    val = val - q;
    valW = valW + w;
    const clone = (ref.cloneNode(true) as HTMLElement);

    document.querySelector('.highcharts-xaxis-labels').appendChild(clone);

    const half = clone.getBoundingClientRect().width / 2;

    clone.style.transform = 'translateX(' + (-valW + difference + half) + 'px)';
    const inner = Math.round(val * 100) / 100;
    clone.innerHTML = inner.toString();
  }
}



最后,我们有一个看起来像这样的图(不是这个给定示例中的数据,而是对于[[20, 0.005], [30, 0.013333333333333334], [20, 0.01], [30, 0.005555555555555555], [20, 0.006666666666666666]]来说,第一个值是宽度,第二个值是高度): enter image description here


可能需要做一些修改才能100%适合您的情况。 F.e.我必须将xAxis的点调整为特定的起点和终点-我省去了这部分。