How can I change the width of the bars in a highch

2019-01-26 00:04发布

With a bar chart like this one, is is possible to change the width of the bars to represent another data attribute, say the weight of the fruits. The heavier the fruit is, the thicker the bar.

You play with the script here. I am open to other javascript plotting libraries that could do that as long as they are free.

$(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]
            }]
        });
    });

});​

3条回答
ゆ 、 Hurt°
2楼-- · 2019-01-26 00:16

I use a set of area charts to simulate a variable-width-column/bar-chart. Say, each column/bar is represented by a rectangle area.

See my fiddle demo (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

查看更多
Melony?
3楼-- · 2019-01-26 00:20

Fusioncharts probably is the best option if you have a license for it to do the more optimal Marimekko charts…

I've done a little work trying to get a Marimekko charts solution in highcharts. It's not perfect, but approximates the first Marimekko charts example found here on the Fusion Charts page…

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

The key is to use a dateTime axis, as that mode provides you more flexibility for the how you distribute points and line on the X axis which provides you the ability to have variably sized "bars" that you can construct on this axis. I use 0-1000 second space and outside the chart figure out the mappings to this scale to approximate percentage values to pace your vertical lines. Here ( http://jsfiddle.net/miken/598d9/2/ ) is a jsfiddle example that creates a variable width column chart.

    $(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();
            }
        });
    });
});

It adds an additional array to allow you to map category names to second tic values to give you a more "category" view that you might want. I've also added code at the bottom that adds vertical dividing lines between the different columns and the bottom line of the chart. It might need some tweaks for the size of your surrounding labels, etc. that I've hardcoded in pixels here as part of the math, but it should be doable.

Using a 'percent' type accent lets you have the y scale figure out the percentage totals from the raw data, whereas as noted you need to do your own math for the x axis. I'm relying more on a tooltip function to provide labels, etc than labels on the chart itself.

Another big improvement on this effort would be to find a way to make the tooltip hover area and labels to focus and be centered and encompass the bar itself instead of the right border of each bar that it is now. If someone wants to add that, feel free to here.

查看更多
混吃等死
4楼-- · 2019-01-26 00:43



pointWidth is what you require to set the width of the bars. try

plotOptions: {
            series: {
                pointWidth: 15
            }
        }


This display bars with the width of 15px. Play around here. Just made an edit to the already existing code.

查看更多
登录 后发表回答