使用Highcharts渲染器在条形图上正确定位

时间:2013-05-07 16:33:36

标签: javascript highcharts

我有一个Highcharts条形图,我正在尝试根据条形值和位置添加自定义形状。首先,我只是尝试使用highcharts.renderer.path,为每个条添加一条线,与条形图一样高,根据硬编码值定位在x轴上。这是我的意思的图片:

example bar chart

这应该很容易,而且是在chart.type =“column”时。在highcharts回调中,我会在每个条上使用getBBox(),并translate()将x轴值转换为像素值。

但是,尝试使用chart.type =“bar”时遇到了几个问题。首先,切换所有x和y值(我假设这是作者首先从柱形图创建条形图的方式)。对于图表的所有属性也是如此:plotLeft现在是顶部,plotTop现在是左边。

这应该有效:

function (chart) {
    $.each(chart.series[0].data, function (pointIndex, point) {
        var plotLine = {},
            elem = point.graphic.element.getBBox(),
            yStart,
            xStart,
            newline;

        yStart = chart.plotTop+elem.x;
        xStart = chart.plotLeft+elem.height;

        plotLine.path = ["M", xStart, yStart+1, "L", xStart, yStart+point.pointWidth];        
        plotLine.attr = {
            'stroke-width': 1,
            stroke: point.color,
            zIndex: 5
        };

        newline = chart.renderer.path(plotLine.path).attr(plotLine.attr).add();
    });        
});

完整示例:http://jsfiddle.net/Bh3J4/9/

第二个问题可能是一个无法克服的错误。看来,当存在多个数据点时,所有x和y值在这些点之间混淆。请注意,颜色与位置不匹配。我创建了issue on GitHub

当只有一点时,这不是问题。当有两个点时,我可以轻松切换值以获得正确的定位。但是当有3个或更多点时,我似乎无法弄清楚这些值如何混淆的逻辑。

第三个问题是,对于条形图,translate函数似乎不适用于xAxis,即使它在yAxis上也是如此。

chart.yAxis[0].translate(4); // correct for bottom axis
chart.xAxis[0].translate(1); // incorrect for side axis

还有另一种方法可以实现我正在寻找的东西吗?我错过了那个小提琴里的东西,这实际上并不是一个错误吗?

3 个答案:

答案 0 :(得分:1)

我能够实现我想要的结果,但我不知道这是巧合还是实际错误的解决方法。无论如何,使用反向排序数组中的x值似乎帮助我正确排列所有内容。这是highcharts的回调函数:

function (chart) {
    var benchmarks = { A: 1.5, B: 3.6, C: 2 },
        reverseData = _.clone(chart.series[0].data).reverse();

    _.each(chart.series[0].data, function (point, pointIndex) {
        var plotLine = {},
            elem = point.graphic.element.getBBox(),
            reverseElem = reverseData[pointIndex].graphic.element.getBBox(),
            benchmark = benchmarks[point.category],
            yStart = chart.plotTop+reverseElem.x,
            xStart = chart.plotLeft+chart.yAxis[0].translate(benchmark),
            yEnd = yStart+point.pointWidth-1;

        plotLine.path = ["M", xStart, yStart+1, "L", xStart, yEnd];        
        plotLine.attr = {
            'stroke-width': 1,
            stroke: "red",
            zIndex: 5
        };        
        chart.renderer.path(plotLine.path).attr(plotLine.attr).add();

        var margin = 5,
            xPadding = 10,
            yPadding = 5,
            xSplit = xPadding/2,
            ySplit = yPadding/2,
            text,
            box;

        text = chart.renderer.text("Top Perf Avg " + benchmark, xStart, yEnd+margin+16).attr({
            color: "#646c79",
            align: "center", 
            "font-family": "Arial, sans-serif",
            "font-size": 9,
            "font-weight": "bold",
            style: "text-transform: uppercase",
            zIndex: 7
        }).add();
        box = text.getBBox();
        chart.renderer.path(["M", box.x-xSplit, box.y-ySplit, 
                             "l", (box.width/2)+xSplit-margin, 0, 
                             margin, -margin, 
                             margin, margin, 
                             (box.width/2)+xSplit-margin, 0,
                             0, box.height+yPadding, 
                             -(box.width+xPadding), 0,
                             0, -(box.height+yPadding)])
                             .attr({
                                'stroke-width': 1,
                                stroke: "#cccccc",
                                fill: "#ffffff",
                                zIndex: 6
        }).add();

    });

}

请在此处查看完整的工作图:http://jsfiddle.net/Bh3J4/18/

答案 1 :(得分:0)

事实上,Highcharts使用transform旋转所有内容,因此请使用相同的方法旋转这些行,请参阅示例:http://jsfiddle.net/Bh3J4/19/

function (chart) {
var d = chart.series[0].data,
    len = d.length;
for(var i =0; i < len; i++){

    var point = d[i],
        plotLine = {},
        elem = point.graphic.element.getBBox(),
        yStart,
        xStart,
        newline;
    console.log(point,point.color);
    xStart = point.plotX - point.pointWidth / 2;
    yStart = point.plotY;

    plotLine.path = ["M", xStart, yStart, "L", xStart+point.pointWidth, yStart];        
    plotLine.attr = {
        transform: 'translate(491,518) rotate(90) scale(-1,1) scale(1 1)',
        'stroke-width': 1,
        stroke: point.color,
        zIndex: 5
    };

    newline = chart.renderer.path(plotLine.path).attr(plotLine.attr).add();
};
}

答案 2 :(得分:0)

轻微调整似乎可以精确对齐:

请注意:更改为xStart / yStart的calc并更改为transform translate参数。 我的方法是让它适用于柱形图,然后进行翻译。 唯一不能令人满意的部分是xStart需要:'{1}}在'列'模式下与xStart = elem.x+chart.plotLeft;在'bar'模式下...

xStart = elem.x;