0

BOUNTY UPDATE: I'm putting a bounty on this, so I wanted to give a little bit more information in case someone comes up with a different solution than modifying my code. The object is to animate the actual category position in HighCharts for bar and column charts. Animating the actual "bar/columns" seems to be built in to HighCharts, however, the label positions is what I'm having trouble with. See below for JSFiddle. Also, I know this question is dealing with SVG, but I need the animation support in IE8 as well.

I'm currently on a mission to animate the reorganization of categories in HighCharts for bar and column charts.

I have bar charts working fine, with the ability to reorganize categories and labels, with labels animating with the following code:

$(this).animate({'svgY': c.labelPositions[myX]}, {'duration': animDuration, 'queue': false});

Now I'm working on the columns, and I'm having significant trouble getting the labels to animate. The code is relatively the same:

$(this).animate({'svgX': c.labelPositions[myX]}, {'duration': animDuration, 'queue': false});

I'm using jQuery SVG to allow the animation of SVG elements, you can find it here.

You can view the jsFiddle I'm working on here. Just click the "Go" buttons under each chart to see them in action.

The actual "hack" to allow category animating is the Highcharts.Series.prototype.update = function(changes, callback){ function.

Just playing around trying to get something to work, I found that I could animate the svgY of the Column labels, but svgX just seems to not function at all.

Actual HighCharts.js hacks are welcome.

MatthewKremer
  • 1,549
  • 1
  • 14
  • 25
  • Neither button does anyting for me in IE8. Firefox does something on the first. – SteveP Mar 13 '13 at 15:25
  • Correct, as I'm animating SVG right now, it will not function in IE8, sorry I should have mentioned that. The columns at least animate for you in Firefox right? Just not the labels? – MatthewKremer Mar 13 '13 at 15:26
  • Yes, the columns on the upper chart animate fine in FF. – SteveP Mar 13 '13 at 15:41
  • The upper chart is the bars, do the columns in the lower chart animate for you? The columns in the bottom chart are animating, but not the labels for me. – MatthewKremer Mar 13 '13 at 15:44
  • And I just discovered that if you click the "Go" button twice on the bottom chart, the labels will update to the correct position instantly, but no animations. – MatthewKremer Mar 13 '13 at 15:45
  • In FF (3.6.28, yes I know it's old !) nothing happens on the bottom chart. Neither colums or labels move. – SteveP Mar 13 '13 at 15:47
  • Any JS errors from Firebug or another examiner? – MatthewKremer Mar 13 '13 at 16:22
  • In chrome I can observe error: `Uncaught TypeError: Cannot read property 'length' of undefined`. Regarding issue - I think it may be caused by fact that you are animating only text tag, while inner tspan also contains `x` property. The same tspan does't have any `y` so maybe that's why it works for bars. – Paweł Fus Mar 14 '13 at 13:16
  • Ah, I'll have to debug the .length in Chrome. The funny part about that tspan thing, is that (outside of the code for my hack), I can animate the inner tspan on X which moves the text, but not the text tag itself. However, even that doesn't function in my code. – MatthewKremer Mar 14 '13 at 13:28

1 Answers1

1

I took a look into your code and improved it a little bit. I did the following:

  • Unified code for column/bar using single variable that stores the attribute we're going to update
  • Removed jQuerySVG dependency, instead my code uses built-in Highcharts animate method
  • Fixed some minor bugs

I tested this with IE7+/Chrome/Firefox, it works fine in all of them.

Here you can find my version of Highcharts.Series.prototype.update:

Highcharts.Series.prototype.update = function (changes, callback) {
    var series = this,
        chart = this.chart,
        options = chart.options,
        axis = chart.xAxis[0],
        ticks = axis.ticks,
        type = chart.options.chart.type,
        animDuration = 400,
        attr = type === 'bar' ? 'y' : 'x',
        animOpt = {},
        text;

    if (options.chart.animation && options.chart.animation.duration) {
        animDuration = options.chart.animation.duration;
    }

    if (type == "bar" || type == "column") {

        if (typeof chart.labelPositions === "undefined") {
            chart.labelPositions = [];

            $.each(ticks, function () {   
                chart.labelPositions.push(this.label[attr]);
            });
        }


        for (var category in changes) {

            for (var i = 0; i < series.points.length; i++) {

                if (typeof series.points[i].originalCategory === "undefined") {
                    series.points[i].originalCategory = series.points[i].category;
                }

                if (series.points[i].originalCategory == category) {

                    $.each(ticks, function () {
                        text = this.label.text || this.label.element.innerHTML; // use innerHTML for oldIE
                        if (text == category) {
                            var myX = (typeof changes[category].x !== "undefined") ? changes[category].x : series.points[i].x;
                            series.points[i].update(changes[category], false, {
                                duration: animDuration
                            });

                            animOpt[attr] = parseInt(chart.labelPositions[myX]);

                            // This is the line that animates the bar chart labels.
                            this.label.animate(animOpt, {
                                'duration': animDuration,
                                'queue': false
                            });

                            return false;
                        }
                    });
                }
            }
        }

        chart.redraw();

        if (typeof callback !== "undefined") {
            setTimeout(function () { callback(); }, animDuration);
        }
    }
}

Check out the demo: http://jsfiddle.net/evq5s/17

slawekkolodziej
  • 693
  • 5
  • 11
  • Thank you very much for taking the time to help me out with this, that looks great! I'll have to do some looking into the built in animation method. Thanks again! – MatthewKremer Mar 21 '13 at 14:02
  • I know it works in the example, but is there any reason you can think of that animating the column chart would only work if a series has six or more items in it? For some reason the graph in my actual project re-calculates the column width and then scrunches all the categories together. – MatthewKremer Mar 26 '13 at 20:57
  • So could you update my demo to show what's exactly not working? – slawekkolodziej Mar 29 '13 at 14:34
  • Got it to work, just removed all non-stock styling etc, made it exactly the same as the example chart, then added one part at a time and somehow it ended up working. Must've been a syntax error or something... – MatthewKremer Mar 30 '13 at 19:01
  • Alright, bug is back, and I finally narrowed down what's causing it. If you end the animation of a column chart with the first category in the first position (in this case Africa at x 0 y 526) the positions get screwed up. Here's a fiddle showing: http://jsfiddle.net/evq5s/18/ Any ideas? – MatthewKremer May 10 '13 at 15:27