0

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

条形图示例

这应该很容易,就是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 值都会在这些点之间混合。请注意小提琴中的颜色与位置不匹配。我在 GitHub 上创建了一个问题

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

第三个问题是,translate 函数似乎不适用于条形图的 xAxis,即使它适用于 yAxis。

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

有没有另一种方法来实现我正在寻找的东西?我是否在那个小提琴中遗漏了实际上不是错误的东西?

4

3 回答 3

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/

于 2013-05-08T22:17:20.050 回答
0

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

请注意:更改 xStart/yStart 的 calc 并更改为 transform translate 参数。我的方法是使其适用于柱形图,然后进行精炼。唯一不满意的部分是 xStart 需要:xStart = elem.x+chart.plotLeft;在“列”模式下与xStart = elem.x;在“栏”模式下......

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 = elem.x;
    yStart = chart.plotHeight - (elem.height/2) + chart.plotTop;

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

    newline = chart.renderer.path(plotLine.path).attr(plotLine.attr).add();
};
}
于 2013-10-17T13:56:51.430 回答
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();
};
}
于 2013-05-09T12:12:09.750 回答