2

I have built an application in flash, it is rather a large application that runs pretty smoothly, however it is a long list of graphs that run further than the application window so I use a vertical scrollbar and a mask to display them.

The problem is everything becomes choppy the further you scroll down, any Tweens or movement and the framerate in general just appears to be much much lower.

When you get to the bottom it is unbearable although there is the same amount of movieclips and same amount of detail throughout the scroll, so I don't see why there should be this massive performance hit for going down a bit.

Anyone have any ideas as to what could be causing this?

As requested here is the part of my code which builds the graphs:

var local_data = SharedObject.getLocal("user_data");
Slide_Tracker = local_data.data.user_data;
var timespan:MovieClip = this.timescale.span;
for (i=0; i<Slide_Tracker.length; i++) {
    var current_date = new Date(Slide_Tracker[i].date_int);
    var date_int:Number = Slide_Tracker[i].date_int;
    var x_range:Number = 30;
    var sorted_date:Object = new Object(sortDate(Slide_Tracker[i].date_int));
    var date_string:String = sorted_date.string;
    var startX:Number = 0;
    date_nav.push(Slide_Tracker[i].date_int);
    if (i == 0) {
        for (s=0; s<Graphs.length; s++) {
            var Chart:MovieClip = Graphs[s].chartArea.createEmptyMovieClip("chart", 10);
            Chart._x = 0;
            Chart._y = 0;
            Charts.push(Chart);
            Chart._parent.dotSpace.index = s;
            Chart._parent.dotSpace.onRollOver = function() {
                this.followDot._visible = true;
                this.followDot.enabled = false;
                this.onMouseMove = function() {
                    if(this._parent.chart.viewPortRatio == undefined) {
                        var viewPortRatio:Number = 1;
                    }
                    else {
                        var viewPortRatio:Number = this._parent.chart.viewPortRatio;
                    }
                    var xMouse:Number = this._xmouse;
                    var xToArray:Number = Math.round(((xMouse-this._parent.chart._x)*viewPortRatio));
                    this.followDot._y = lineArray[this.index][xToArray].y;
                    trace(xToArray);
                    this.followDot._x = xMouse;
                };
            };
            Chart._parent.dotSpace.onRollOut = function() {
                this.followDot._visible = false;
                delete this.onMouseMove;
            };
        }
    } else if (i>0) {
        var past_date:Date = new Date(Slide_Tracker[i-1].date_int);
        var date_diff:Number = Math.round((current_date-past_date)/86400000);
    }
    for (s=0; s<Slide_Tracker[i].val_arr.length; s++) {
        var Slide_y:Number = 100-Slide_Tracker[i].val_arr[s];
        var Chart:MovieClip = Graphs[s].chartArea.chart;
        with (Chart) {
            beginFill(0x000066,15);
            lineStyle(2,0x000066,80);
            if (i == 0) {
                moveTo(startX,Slide_y);
                Xcoords[s].push(startX);
                Ycoords[s].push(Slide_y);
            } else if (i>0) {
                var index:Number = Xcoords[s].length-1;
                var prevX:Number = Xcoords[s][index];
                var prevY:Number = Ycoords[s][index];
                moveTo(prevX,prevY);
                var newX:Number = prevX+(date_diff*(895.9/x_range));
                var newY:Number = Slide_y;
                lineTo(newX,newY);
                lineStyle(6,0x000066,0);
                lineTo(newX,100);
                lineTo(prevX,100);
                lineTo(prevX,prevY);
                convertLineToArray(s,prevX,newX,prevY,newY);
                Xcoords[s].push(newX);
                Ycoords[s].push(newY);
            }
            endFill();
            lineStyle(0,0x000066,80);
            with (Graphs[s].chartArea.timescale.span) {
                var barName:String = Slide_Tracker[i].date_int;
                var thisBar:MovieClip = attachMovie("bar", barName, this.getNextHighestDepth()+i);
                if (Slide_y != 100) {
                    var barY:Number = 100-Slide_y;
                } else {
                    var barY:Number = 0;
                }
                if (i == 0) {
                    thisBar._x = 1;
                    thisbar._height = barY/4;
                    spanXcoords[s].push(1);
                    spanYcoords[s].push(barY/4);
                } else if (i>0) {
                    var index:Number = spanXcoords[s].length-1;
                    var spanPrevX:Number = spanXcoords[s][index];
                    var spanPrevY:Number = spanYcoords[s][index];
                    var spanNewX:Number = spanPrevX+(date_diff*3);
                    var spanNewY:Number = barY/4;
                    thisBar._x = spanNewX;
                    thisBar._height = barY/4;
                    spanXcoords[s].push(spanNewX);
                    spanYcoords[s].push(spanNewY);
                }
                thisBar._y += 25;
                selector_bars[s].push(thisBar);
            }
        }
        Chart.setMask(Chart._parent.chart_mask);
        var dot_name:String = new String(Graphs[s]._name+"_dot"+i);
        var dotObj:Object = new Object();
        if (prevX != undefined) {
            dotObj._x = newX;
        } else {
            dotObj._x = startX;
        }
        dotObj._y = Slide_y;
        Chart._parent.dotArea.attachMovie("graph_dot",dot_name,Graphs[s].chartArea.dotArea.getNextHighestDepth(),dotObj);
        Chart._parent.dotArea.swapDepths(99999);
        var thisDot:MovieClip = eval(Graphs[s]+".chartArea.dotArea."+dot_name);
        Graphs_dots[s].push(thisDot);
        thisDot.date_string = date_string;
        thisDot.date_int = date_int;
        thisDot.percent = Slide_Tracker[i].val_arr[s];
        thisDot.onRollOver = function() {
            this.gotoAndStop("over");
            var dot_Coords:Object = {x:this._x, y:this._y};
            var viewPortRatio:Number = this._parent._parent.chart.viewPortRatio;
            var offsetX:Number = this._parent._parent.chart.offsetX;
            if (viewPortRatio == undefined) {
                viewPortRatio = 1;
            }
            if (offsetX == undefined) {
                offsetX = 0;
            }
            var text_x:Number = (dot_Coords.x/viewPortRatio)+offsetX;
            var text_y:Number = dot_Coords.y;
            if (dot_Coords.y<50) {
                text_y += 60;
            } else {
                text_y -= 20;
            }
            var Textbox:Object = {name:"dot_info", container:this._parent._parent._parent, x:text_x, y:text_y, text:this.date_string+"\n"+this.percent+"%"};
            var dotText:TextField = generateTextbox(Textbox);
            if (dotText._x>448) {
                dotText._x -= dotText._width;
            }


        };
        thisDot.onRollOut = thisDot.onReleaseOutside=function () {
            this.gotoAndStop("norm");
            killTxt(this._parent._parent._parent.dot_info);
            delete dot_Coords;
        };

    }
    chartsWidth = Chart._width;
}

And here is my scrollbar code:

scrolling = function () { 
var scrollHeight:Number = scrollTrack._height - btnUp._height - btnDown._height; 
var contentHeight:Number = contentMain._height; 
var scrollFaceHeight:Number = scrollFace._height; 
var maskHeight:Number = maskedView._height; 
var initPosition:Number = scrollFace._y=scrollTrack._y + btnUp._height; 
var initContentPos:Number = contentMain._y; 
var finalContentPos:Number = maskHeight-contentHeight+initContentPos; 
var left:Number = scrollTrack._x + (scrollTrack._width - scrollFace._width)/2.4; 
var top:Number = scrollTrack._y + btnUp._height; 
var right:Number = scrollTrack._x + (scrollTrack._width - scrollFace._width)/2.4; 
var bottom:Number = (scrollTrack._height-scrollFaceHeight+scrollTrack._y) - btnDown._height; 
var dy:Number = 0; 
var speed:Number = 10; 
var moveVal:Number = (contentHeight-maskHeight)/(scrollHeight-scrollFaceHeight); 

scrollFace.onPress = function() { 
var currPos:Number = this._y; 
startDrag(this, false, left, top, right, bottom); 
this.onMouseMove = function() { 
dy = Math.abs(initPosition-this._y); 
contentMain._y = Math.round(dy*-1*moveVal+initContentPos);
};
}; 
scrollFace.onMouseUp = function() { 
stopDrag(); 
delete this.onMouseMove;
}; 
btnUp.onPress = function() { 
this.onEnterFrame = function() { 
if (contentMain._y+speed<maskedView._y) { 
if (scrollFace._y<=top) { 
scrollFace._y = top;
} else { 
scrollFace._y -= speed/moveVal;
} 
contentMain._y += speed;
} else { 
scrollFace._y = top; 
contentMain._y = maskedView._y; 
delete this.onEnterFrame;
}
};
}; 
btnUp.onDragOut = function() { 
delete this.onEnterFrame;
}; 
btnUp.onRollOut = function() { 
delete this.onEnterFrame;
}; 
btnDown.onPress = function() { 
this.onEnterFrame = function() { 
if (contentMain._y-speed>finalContentPos) { 
if (scrollFace._y>=bottom) { 
scrollFace._y = bottom;
} else { 
scrollFace._y += speed/moveVal;
} 
contentMain._y -= speed;
} else { 
scrollFace._y = bottom; 
contentMain._y = finalContentPos; 
delete this.onEnterFrame;
}
};
}; 
btnDown.onRelease = function() { 
delete this.onEnterFrame;
}; 
btnDown.onDragOut = function() { 
delete this.onEnterFrame;
}; 
var mouseListener = new Object();
mouseListener.onMouseWheel = function( wheelMotion )
{
if (wheelMotion < 0) {
if (contentMain._y-speed>finalContentPos) { 
if (scrollFace._y>=bottom) { 
scrollFace._y = bottom;
} else { scrollFace._y += speed/moveVal;
} 
contentMain._y -= speed;
} else { 
scrollFace._y = bottom; 
contentMain._y = finalContentPos; 
}
}
if (wheelMotion > 0) {
if (contentMain._y+speed<maskedView._y) { 
if (scrollFace._y<=top) { 
scrollFace._y = top;
} else { 
scrollFace._y -= speed/moveVal;
} 
contentMain._y += speed;
} else { 
scrollFace._y = top; 
contentMain._y = maskedView._y; 
}
}
}

Mouse.addListener( mouseListener );



if (contentHeight<maskHeight) { 
scrollFace._visible = false; 
btnUp.enabled = false; 
btnDown.enabled = false;
btnUp.gotoAndStop(2);
btnDown.gotoAndStop(2);
} else { 
scrollFace._visible = true; 
btnUp.enabled = true; 
btnDown.enabled = true;
btnUp.gotoAndStop(1);
btnDown.gotoAndStop(1);
}
}; 
scrolling();
George Reith
  • 13,132
  • 18
  • 79
  • 148
  • are you adding the further movie clips to the display list on scroll down and what about when you once scroll down and come back to top of scroll is it gone twice slower or gets better when you comeback to top – Badr Jul 18 '11 at 11:16
  • gets better when you scroll back up, the elements below exist as soon as the person enters the frame and are static apart from a change in Y value when scrolled. – George Reith Jul 18 '11 at 11:21
  • Updated, this only comes in to effect when there is a lot of graph data, until then it scrolls and plays smoothly. But it still shouldn't get worse as you scroll down right? – George Reith Jul 18 '11 at 12:37
  • 1
    the code seems good enough and there is some good practices that can make it better, only recommendations to you that divide the graph data working and rendering in different frames divide the processing in chunks instead to do it in one go as it will expand the frame and UI rendering will show delays, and use the garbage collector if necessary i think there will not me memory issue with this but in case you face memory problem us GC. best of luck – Badr Jul 19 '11 at 06:06
  • Thanks, just I'm a little unsure as to what you mean by dividing the data working and rendering, do you mean build the graphs in one frame and display them in the next? – George Reith Jul 19 '11 at 08:15

1 Answers1

0

I solved this today and what a relief, I just ran into the scrollRect() function which only renders the data which is viewable within it's bounds as long as it is bitmap cached (vector objects will still be rendered in full whether viewable or not).

Despite the fact I let the user modify the _scaleX of the graphs and caching them as a bitmap now I still see an absolutely huge performance increase since swapping my masks with a scrollable rectangle, as after enough data these graphs were over 20,000 in width. Despite their humongous size everything works fluidly.

Adobe's explanation of scrollRect()

George Reith
  • 13,132
  • 18
  • 79
  • 148