JavaScript not performing SVG changes Incrementally


Posted by Cyrille apropos on Wed Aug 27th, 2008 at 21:54:35 BST

In an attempt to get smooth transitions within an SVG bar graph that can display data equally distributed or chronologically on the x axis I have run into some confounding complications.
While all the bar elements incrementally change their x coordinates after each iteration, none of these increments are visible. The SVG bar graph jumps from one state to another once the transition has completed.
While this would be easy to do using animations, Firefox requires a JavaScript workaround.

In an attempt to get smooth transitions within an SVG bar graph that can display data equally distributed or chronologically on the x axis I have run into some confounding complications.
While all the bar elements incrementally change their x coordinates after each iteration, none of these increments are visible. The SVG bar graph jumps from one state to another once the transition has completed.


While this would be easy to do using animations, Firefox requires a JavaScript workaround.


It seems like it must finish executing the changes completely before it can try and refresh the SVG graphic - is this normal? Inserting pauses have no effect, the only clear way of showing the changes are to have alert() statements after each iteration - but this is clearly not an option.


The issue is not caused by the PC simply processing the changes so fast that they are not visible since even with pauses the changes do not take affect until completion.


I've added the function below and would be happy to hear what others think - is this expected or am I simply missing something? The code below is embedded at the bottom of an SVG file (here):


    //a svg 'button' calls the function to display the bar graph in either 'equally' or 'temporally' mode
    function distribute(mode)
    {
        //the number of steps between the transitions, more equals smoother
        var speed = 100;
        //create arrays to store the bar data before changing its properties
        var curData = new Array();
        var altData = new Array();
        var spacing = new Array();


       //go through each 'bar0' to 'barN' while element not null and repopulate arrays as well saving the data in the svg objects for next button press
        var i=0;
        var element = null;
        while((element = document.getElementById('bar' + i)) != null)
        {
            curData[i] = parseFloat(element.getAttributeNS(null, 'x1'));
            altData[i] = parseFloat(element.getAttributeNS(null, 'x3'));
            element.setAttributeNS(null, 'x3', curData[i]);
            spacing[i] = parseFloat((curData[i] - altData[i])/speed);
            i++;
        }
        //we should now have all the current equal spacing as well as date based spacing


       //make the appropriate buttons visible and hidden
        if(mode == 'temporally')
        {
            document.getElementById('diste').setAttributeNS(null, 'visibility', 'visible');
            document.getElementById('distt').setAttributeNS(null, 'visibility', 'hidden');
        } else {
            document.getElementById('diste').setAttributeNS(null, 'visibility', 'hidden');
            document.getElementById('distt').setAttributeNS(null, 'visibility', 'visible');
        }


       //go through each bar a number of times defined by 'speed' and move the bar a fraction of what it needs cover
        var barcount = curData.length;
        var j;
        for(var j = 0; j < speed; j++)
        {
            //go through each bar and budge it
            for(var i = 0; i < barcount; i++)
            {
                var element = document.getElementById('bar' + i);
                if(curData[i] < altData[i])
                {
                    //push it right
                    element.setAttributeNS(null, 'x1', curData[i]-=spacing[i]);
                    element.setAttributeNS(null, 'x2', curData[i]);
                } else {
                    //push it left
                    element.setAttributeNS(null, 'x1', curData[i]-=spacing[i]);
                    element.setAttributeNS(null, 'x2', curData[i]);
                }
            }
        }


       //note that the elements may not be exactly located due to unit incrementation above
        //they may be off by up to .999- points
        //this is fixed here
        for(var i = 0; i < barcount; i++)
        {
            element = document.getElementById('bar' + i);
            element.setAttributeNS(null, 'x1', altData[i]);
            element.setAttributeNS(null, 'x2', altData[i]);
        }
    }

Display: Sort:
Display: Sort:
Login

Make a new account

Username:
Password: